ObjectMapper Java對象與JSON的互換,項目中用到,個人理解

ObjectMapper是一個高效轉化json格式數據的類,如果創建的是spring boot項目,會自動導入com.fasterxml.jackson 依賴包,我使用的是這個類ObjectMapper。 
maven依賴: 

com.fasterxml.jackson.core 
jackson-databind 

2.8.3 

一:controller 後臺接收json串,讀取數據,通常轉換格式 Map / javaBean  (注意:不支持泛型如List<T>)

類型可以是List/Map/Set 數組 或者是普通的Bean,但如果要轉換成的類型是List<Person>類型,會出現轉換錯誤ClassCastException,

ObjectMapper在轉化List時,返回的是List<LinkedHashMap> ,因爲任何對象都可以用Map來表示。

項目案例:

/**
 * 將JSON字符串轉換爲對象
 *
 * @param json      JSON字符串
 * @param valueType 對象類型
 *
 * @return 對象
 */
public static <T> T toObject(String json, Class<T> valueType) {
    Assert.hasText(json);
    Assert.notNull(valueType);
    try {
        return mapper.readValue(json, valueType);
    } catch (Exception e) {
        logger.error("ERROR:", e);
    }
    return null;
}
二:向界面傳參Java對象轉換成json字符串
項目案例:
/**
 * 將對象轉換爲JSON字符串
 *
 * @param value 對象
 *
 * @return JSOn字符串
 */
public static String toJson(Object value) {
    try {
        return mapper.writeValueAsString(value);
    } catch (Exception e) {
        logger.error("ERROR:", e);
    }
    return null;
}


其中mapper 對象定義如下(常用序列化設置屬性jar自帶封裝):

private static ObjectMapper mapper = new ObjectMapper()
        .setSerializationInclusion(Include.NON_NULL)
        .enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        .enable(MapperFeature.USE_ANNOTATIONS);
註釋:
setSerializationInclusion:
//設置序列化配置(全局),設置序列化時不輸出空值. 

SerializationFeature.WRAP_ROOT_VALUE:

是否環繞根元素,默認false,如果爲true,則默認以類名作爲根元素,你也可以通過@JsonRootName來自定義根元素名稱

SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:序列化日期時以timestamps輸出,默認true

MapperFeature.USE_ANNOTATIONS 或者用註解  @JsonAutoDetect(作用在類上)來開啓/禁止自動檢測

下面是在網上看的一些比較好的解釋:
在轉化過程中需要注意的問題: 
有可能會遇到json反序列化的問題。當你對象中有get***()的地方,它就當做它是一個屬性,所以當你序列化json之後,在反序列化的時候,很有可能會出現異常的情況,因爲在你的model中沒有這個屬性的定義。 
那該如何處理和解決呢? 
jackson給出了它自己的解決方案(JacksonHowToIgnoreUnknow): 
1. 在class上添加忽略未知屬性的聲明:@JsonIgnoreProperties(ignoreUnknown=true) 
2. 在反序列化中添加忽略未知屬性解析,如下:

 1 /**
 2  * json deserialize
 3  * @param json
 4  * @param mapClazz
 5  * @return
 6 */
 7 public static Object jsonDeserialize(final String json, final Class<?> mapClazz) {
 8     ObjectMapper om = new ObjectMapper();
 9     try {
10         // 忽略未知屬性
11         om.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
12         return om.readValue(json, mapClazz);
13     } catch (Exception ex) {
14         return null;
15     }
16 }

3. 添加"Any setter"來處理未知屬性
1 // note: name does not matter; never auto-detected, need to annotate
2 // (also note that formal argument type #1 must be "String"; second one is usually
3 // "Object", but can be something else -- as long as JSON can be bound to that type)
4 @JsonAnySetter
5 public void handleUnknown(String key, Object value) {
6     // do something: put to a Map; log a warning, whatever
7 }

備註:

如果是ArrayList<javaBean>那麼使用ObjectMapper 的getTypeFactory().constructParametricType(collectionClass, elementClasses);

如果是HashMap<String,javaBean>那麼 ObjectMapper 的getTypeFactory().constructParametricType(HashMap.class,String.class, javaBean.class);

項目中案例:
public static <T> List<T> doToResp(List list, Class<T> c) {

    if (null == list) {
        return null;
    }
    String json = JsonUtils.toJson(list);

    JavaType javaType = JsonUtils.getCollectionType(List.class, c);
    List<T> t = JsonUtils.toObject(json, javaType);
    return t;
}
其中
JsonUtils.getCollectionType(List.class, c); 轉換泛型,詳解如下:
public static JavaType getCollectionType(Class<?> collectionClass,
        Class<?>... elementClasses) {
    return mapper.getTypeFactory().constructParametricType(collectionClass,
            elementClasses);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章