1. 程式人生 > >spring學習筆記---Jackson的使用和定製

spring學習筆記---Jackson的使用和定製

http://www.cnblogs.com/mumuxinfei/p/4761374.html

****************************************

前言:
  JAVA總是把實體物件(資料庫/Nosql等)轉換為POJO物件再處理, 雖然有各類框架予以強力支援. 但實體物件和POJO, 由於"飲食習慣", "民族特色", "地域區別"等等差異, 需要有些定製需求, 使得能夠完美的對映. 這個性化定製需求, 包括名稱/時間格式/欄位過濾等等約定.
  springmvc的學習筆記系列:
  • idea建立springmvc專案
  • 面向移動端支援REST API
  本文講講述如何把pojo物件轉化為約定好的json資料格式. 權當筆記.

疑問篇:
  springmvc在使用註解@ResponseBody返回一個POJO物件時, 其內部會藉助Jackson來完成POJO轉化為JSON的工作.
  比如對於如下的POJO類:

public class Message {
 
  private String userId; // 使用者id
 
  private String message; // 訊息實體
 
  private Date timestamp; // 時間資訊, yyyy-MM-dd HH:mm:ss
 
  private String extra; // 額外附帶資訊
 
}


  其最終講轉換為如下的json格式:
  

{"user_id":"1001","message":"message","timestamp":"2015-08-31 12:16:30"}


  如果開發者需要如下需求:
  1). json實體的key命名規則, 全小寫化, 不同單詞以"_"字元連線.
  2). 返回時間欄位, 需滿足"yyyy-MM-dd HH:mm:ss"格式
  3). 省略掉extra欄位

  由此可見我們的最終目標是:
{"user_id":"1001","message":"message","timestamp":"2015-08-31 12:16:30"}

解決篇:
  • 重新命名
  jackson對重新命名的處理, 引入註解JsonProperty

來實現. 其對單個屬性配置有效.

@JsonProperty(value="user_id")
private String userId; // 使用者id

注: value屬性設定為使用者想要的命名即可.
  當然還有另一種方式註解方式, 是JsonNaming, 其修飾於POJO類上. 用於對所有屬性, 進行統一的命名轉換.

     
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class Message {
  ...
}


 注: PropertyNamingStrategy就非常漂亮地把所有的類屬性名稱都轉換為小寫, 同時單詞(駝峰命令法)之間使用'_'字元來分割.
  自定義的Strategy類, 需要實現如下抽象類:

public abstract class PropertyNamingStrategy implements Serializable {
  public abstract static class PropertyNamingStrategyBase extends PropertyNamingStrategy {
    public abstract String translate(String var1);
  }
}


 • 欄位可見性
  過濾某些欄位屬性, jackson引入了註解JsonIgnore. 其對單個屬性生效.

       @JsonIgnore private String extra; // 額外附帶資訊  

還有另外一種方式, 是採用JsonIgnoreProperties, 其修飾POJO類, 指定一組需要忽略的欄位.

1 2 3 4 5 // *) 字典{}內是property name列表 @JsonIgnoreProperties({"extra","extra1", "extra2"}) public class Message {   ... }

  • 自定義序列化/反序列化
  jackson採用@JsonSerialize@JsonDeserialize來實現自定義序列化/反序列化的實現. 如之前的時間欄位作為例子.
  定義時間序列化的實現類.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class Message { @JsonSerialize(using=DemoDateSerializer.class) @JsonDeserialize(using=DemoDateDeserializer.class) privateDate timestamp; // 時間資訊, yyyy-MM-dd HH:mm:ss } // *) JSON的序列化類 class DemoDateSerializer extends JsonSerializer<Date> { @Override publicvoid serialize(Date value, JsonGenerator jgen, SerializerProvider provider)throws IOException, JsonProcessingException {     DateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     jgen.writeString(dateFormat.format(value));   } } // *) JSON的反序列化類 class DemoDateDeserializer extends JsonDeserializer<Date> { @Override publicDate deserialize(JsonParser jp, DeserializationContext dctx)throws IOException, JsonProcessingException {     DateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try{ returndateFormat.parse(jp.getValueAsString());     } catch(ParseException e) {       e.printStackTrace();     } finally{     } returnnull;   } }

  除了常規的時間格式轉換, 還能正則提取等功能. 序列化和反序列化的自定義, 使得Jackson更加的強大. 猶如hive中的UDF函式.

實驗效果:
  最終的定義的類修改如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Message { @JsonProperty(value="user_id") privateString userId; // 使用者id privateString message; // 訊息實體 @JsonSerialize(using=DemoDateSerializer.class) @JsonDeserialize(using=DemoDateDeserializer.class) privateDate timestamp; // 時間資訊, yyyy-MM-dd HH:mm:ss @JsonIgnore privateString extra; // 額外附帶資訊 }

  最終的效果如圖所示:
  
  與最初期望的效果保持一致, 值得小小慶祝一下.

總結:
  jackson還有很多高階的用法, 比如破除迴圈引用的處理機制, 多類別的處理等等. 這邊暫時忽略, 本文參考了博文"jackson annotations註解詳解" , 深表敬意和感謝. 

寫在最後:
  
如果你覺得這篇文章對你有幫助, 請小小打賞下. 其實我想試試, 看看寫部落格能否給自己帶來一點小小的收益. 無論多少, 都是對樓主一種由衷的肯定.