Jackson: 編寫自己的欄位格式化方法

2021-02-13 背井

Jackson[1] 是我們編寫 Java 應用時常用的 JSON 序列化/反序列化庫。今天說說使用它的另一個技巧:為特定欄位編寫自己的序列化方法(或者,在序列化前,怎麼先格式化特定欄位)。

之前介紹過的 Jackson 的技巧:巧用 @JsonRawValue 註解。

假設某 API 返回的 JSON 結構如下:

{
  "a": 10000,
  "b": 12345
}

前端拿到該數據後,要做如下渲染:

即,數字要轉化為「萬」,且保留一位小數。

關於數值格式化,通常的做法是以下 2 種:

後端返回原始數值,前端拿到數值後,先格式化再顯示。

缺點:前端需要寫格式化邏輯;當前端有多端時(web / ios / android),每一端都要寫自己的格式化函數。

後端直接返回格式化後的欄位,前端拿到數據後直接顯示。

優點:前端只需要負責顯示,無需額外邏輯;當涉及多平臺時,省了前端重複的工作量。缺點:後端不能偷懶了;當這些數字還需要在前端參與數學運算時,只返回格式化的文本是不夠的。

本文說說採用2讓後端直接返回格式化後的欄位,有沒有好的實現方式。

2 的返回格式如下:

{"a":"1w","b":"1.2w"}

我們先討論一下兩種可能的實現方法。

假設有 ModelDto 類如下:

@Data
class Model {
    int a;
    int b;
}

@Data
class Dto {
    String a;
    String b;
}

另外有一個格式化數值的方法:

// 格式化數值
String format(int num){
   // 省略
}

方式一:手動轉換

即 一個欄位一個欄位的拷貝,拷貝前先轉換一下:

// 手動調用格式化方法
dto.setA(format(model.getA()));
dto.setB(format(model.getB()));

這種方式雖然能達到目的,但每個需要格式化的欄位都需要手動調用 format 方法,就問你煩不煩?

而且,像這類從一個 bean 轉換到另一個 bean 的操作,由於兩邊欄位類型不同,也不能方便地使用 MapStruct 等工具自動轉換,是不是更煩了?

所以我們引入方法二。

方法二:利用註解,聲明式配置

其實,Jackson 允許我們在序列化對象時,指定某個欄位的序列化方式,如下面這樣:

先改寫 Dto 類,保持欄位類型和 Model 一致,然後給各個欄位加一個註解配置:

@Data
class Dto {
    @JsonSerialize(converter = MyConverter.class)
    int a;
    @JsonSerialize(converter = MyConverter.class)
    int b;
}

其中,@JsonSerialize 註解用來進行個性化配置,converter 參數的作用,是在序列化指定欄位之前,用指定轉換器先進行轉換操作,Jackson 再對轉換後的結果進行序列化。

MyConverter 類的實現如下:

import com.fasterxml.jackson.databind.util.StdConverter;

class MyConverter 
   extends StdConverter<Integer, String> {

    @Override
    public String convert(Integer num) {
        // 格式化數值
        return format(num);
    }
}

如此,該 Dto 中的 ab 欄位,在序列化之前,會先被格式化,即:

對於

{
  "a": 10000,
  "b": 12345
}

會自動轉換成

{
  "a": "1w",
  "b": "1.2w"
}

利用註解配置的好處是:

當某天需求變動,不需要返回格式化的文本或格式化算法有調整時,可以通過修改 MyConverter 類來統一更改。避免了每個欄位都要去手動調用 format 的繁瑣。由於 ModelDto 欄位名和類型一樣,方便使用 MapStruct 等工具自動生成轉換類。 總結

文章介紹了 Jackson 工具庫在序列化 Java Bean 時,利用 @JsonSerialize 註解的 converter 配置項,可以輕鬆定製欄位的序列化方式。該註解還有別的屬性可配置,建議讀者查看文檔進一步學習。

參考資料[1]

FasterXML/jackson: https://github.com/FasterXML/jackson

- END -

轉發支持作者🍻

相關焦點

  • 聽說你還在用SimpleDateFormat格式化日期
    有個坑技術部每個月都會組織一下代碼走查及優化,以前是各自審查優化自己的項目,如今幾位老哥的離職他們的項目就落到了我的頭上。對於程式設計師來說最痛苦的事情就是接手別人的項目,還要做優化改造,因為這一點也不比重構一遍項目簡單。不過,軍令在前,沒辦法硬著頭皮上吧!
  • Jackson,最牛掰的 Java JSON 解析器
    ,需要符合以下規則:如果欄位的修飾符是 public,則該欄位可序列化和反序列化(不是標準寫法)。如果欄位的修飾符不是 public,但是它的 getter 方法和 setter 方法是 public,則該欄位可序列化和反序列化。getter 方法用於序列化,setter 方法用於反序列化。如果欄位只有 public 的 setter 方法,而無 public 的 getter 方 法,則該欄位只能用於反序列化。
  • Jackson 屬性自定義命名策略
    ;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.PropertyNamingStrategy;import com.fasterxml.jackson.databind.annotation.JsonNaming
  • 聊一聊:Python格式化字符串
    作者:田小計劃出處:http://www.cnblogs.com/wilber2013/在編寫程序的過程中,經常需要進行格式化輸出,每次用每次查。格式化操作符(%)"%"是Python風格的字符串格式化操作符,非常類似C語言裡的printf()函數的字符串格式化(C語言中也是使用%)。
  • 程式設計師:JSON學習,FastJson和Jackson對null的處理
    那就要仔細看看fastjson轉換java對象為json的時候的入參了:也就是這個方法:JSONObject.toJSONString(Object object, SerializerFeature... features)Fastjson的SerializerFeature序列化屬性:QuoteFieldNames———-輸出key時是否使用雙引號
  • 初識pycharm編寫方法
    使用pycharm編輯器 雙擊我們安裝好的pycharm編輯器(安裝過程在前幾節)選擇第一個新建項目第一個pure python是純python,下面的那些是一些擴展,暫時不用,我們就選第一個Location是選擇編寫代碼保存的路徑,根據自己的情況點右側小文件夾按鈕,自行選擇一個路徑保存即可保存後點擊右下角的
  • python字符串格式化深入詳解(四種方法)
    一、使用 % 符號來進行格式化格式符為真實值預留位置,並控制顯示的格式。(3)width表示顯示寬度(4)precision表示小數點後精度 注意:百分號% 來格式化字符串是最早出現的,python裡面稱之為printf風格的字符串格式化,參考官方文檔:https://docs.python.org/zh-cn/3.7/library/stdtypes.html#old-string-formatting
  • 在MySQL中使用XML數據—數據格式化
    今天我將介紹如何更好地格式化XML輸出內容。        在MySQL中使用XML數據 http://tech.it168.com/a2009/1211/822/000000822827.shtml  在ExtractValue()函數輸出中添加我們自己的標題  在上一篇文章中,我們使用LOAD_FILE()函數導入了一個XML文檔,然後使用ExtractValue()函數提取了某些欄位
  • Python字符串類型的格式化
    字符串格式化用於解決字符串和變量同時輸出時的格式安排。字符串是程序向控制臺、網絡、文件等介質輸出運算結果的主要形式之一,為了能提供更好的可讀性和靈活性,字符串類型的格式化是運用字符串類型的重要內容之一。Python語言同時支持兩種字符串格式化方法,我們本課題要學習的是format()格式化方法,採用format()方法進行字符串格式化。
  • java日期和時間的格式化
    在編寫程序時,經常需要對日期進行格式化輸出。使用String類的format方法可以實現對日期和時間的格式化輸出。日期的格式化輸出Java提供了日期格式化轉換符用於支持日期的格式化輸出,格式化轉換符如下表所示: 案例1:使用API庫的Date類獲取當前日期和時間信息,並用format()方法將日期格式化為
  • 60行Python代碼編寫資料庫查詢應用
    而在今天的教程內容中,我將帶大家學習Dash中渲染網頁靜態表格的常用方法,並在最後的例子中教大家如何配合Dash,簡簡單單編寫一個資料庫查詢應用~圖12 在Dash中渲染靜態表格在Dash中渲染「靜態」表格,方法有很多,而我們今天要學習的方法,是配合之前文章介紹過的第三方拓展
  • 欄位校驗規範&欄位庫建立
    所以我們將之前的內容進行雕琢,更新了欄位校驗模板,規範了團隊中各角色的協同方式,並且提出了新的提升團隊效能的方法——欄位庫。下面將會給大家詳細描述。上面講述的關於欄位規範的表格模板及其協作方法、工作流程的定義已經能夠解決我們之前調研總結出的大部分問題: 問題1 :不太清楚欄位校驗表格如何使用、填寫規則等,在工作流程和撰寫方法上沒有明確定義。
  • 如何使用Python 進行格式化輸出?
    ,並沒有對比過這些輸出有什麼異同,也並不清楚該用哪種格式化輸出方式比較合適,因此,今天就要幫大家梳理下Python的格式化輸出方式。目前,Python 總共支持三種格式化輸出方式,分別是:%-formatting 格式化輸出方式str.format 格式化輸出方式f-Strings 格式化輸出方式其中前兩種是比較老的格式化輸出方式,這兩種方式會簡單介紹一下,當你下次看到這類代碼的時候,能夠支持它是格式化輸出就行了,但你自己在編寫代碼的時候,強烈建議使用第三種格式化輸出方式
  • 怎麼強制格式化SD卡?SD卡修複方法
    畢竟格式化SD卡給我們帶來的麻煩很大,而且有時候甚至無法格式化。接下來就為大家介紹一下遇到這種情況修復SD卡的方法。首先先簡單給大家科普一下SD卡遇到這種情況的原因。一般來說正常使用的SD卡很少會因為自己的故障出錯,一般原因都來自於外部,比如我們在使用SD卡的時候的一些壞習慣和病毒等等原因。
  • 內存卡格式化不了怎麼辦?這些方法幫您修復
    內存卡格式化不了怎麼辦?內存卡是一種廣泛存在於各種媒體設備中的小型存儲裝置,起到記憶存儲媒體設備文件的作用。但是有時候內存卡會出現一些故障,需要格式化修復但又提示無法格式化,這時候該怎麼去修復內存卡呢?下面介紹的這幾種方法非常好用,快來學習嘗試一下吧。
  • Python format()格式化輸出方法詳解
    format() 方法的語法格式如下:str.format(args)此方法中,str 用於指定字符串的顯示樣式
  • 淺析win7電腦中格式化U盤幾種方法
    小夥伴們留言詢問,當我們在格式化U盤的時候,會出現提示「Windows無法完成格式化」,導致格式化失敗,反覆試過幾次,其結果都是一樣
  • 無法格式化怎麼辦?首先方法要用對
    但是由於對sd卡的操作不當,常常會出現一些奇怪的問題,比如說不能格式化,那麼萬一sd不能格式化的話,我們該怎麼辦呢?這就來給大家介紹一下。關於sd卡的修複方法還不少,給大家先介紹第一種,藉助開始運行進行修復。
  • 如何編寫簡潔美觀的Python代碼
    你會有很多的數據幀、列表、函數、繪圖等,如果不遵循正確的格式準則,你甚至會很容易失去對自己代碼的跟蹤!協作如果你在一個團隊項目上合作,大多數數據科學家都會這樣做,那麼好的格式化就成了一項必不可少的任務。
  • Mysql 兩個日期欄位相減得到秒
    前言:測試工程師日常,為了驗證欄位:平均回復時長 顯示是否正確,所以需要將2個日期欄位進行相減,得出的數據轉化為小時,然後看小時落在哪個區間端裡邊