jackson解析之(1)註解序列化

1. 依賴

Jackson庫,是基於java語言的開源json格式解析工具。Jackson兩大分支codehausfasterxml。參考:Jackson兩大分支codehaus、fasterxml的區別
Jackson從2.0開始改用新的包名fasterxml,1.x版本的包名是codehaus。若是是新項目,建議直接用2x,即fasterxml jackson
整個庫包含3個jar包:html

<!-- Jackson依賴庫 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <!--2.8.8-->
    <version>${dependency.version.jackson}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${dependency.version.jackson}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${dependency.version.jackson}</version>
</dependency>

說明java

  1. jackson-core——核心包(必須),提供基於「流模式」解析的API。
  2. jackson-databind——數據綁定包(可選),提供基於「對象綁定」和「樹模型」相關API。
  3. jackson-annotations——註解包(可選),提供註解功能。

其餘數據庫

在時候用mybatis時,還有如下包,用於映射LocalDateTime與數據庫中的time:json

<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis-typehandlers-jsr310</artifactId>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

2. 典型註解

1) @JsonSerialize

該註解部分源碼以下:mybatis

package com.fasterxml.jackson.databind.annotation;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonSerialize {
    Class<? extends JsonSerializer> using() default None.class;

    Class<? extends JsonSerializer> contentUsing() default None.class;

    Class<? extends JsonSerializer> keyUsing() default None.class;

    ...

說明app

  • 該註解存在於運行RUNTIME時,可反射獲取;
  • 做用範圍可用於類、方法、字段等;
  • 一般使用using字段,傳入格式爲繼承了JsonSerializer的類的字節碼Class<? extends JsonSerializer>

JsonSerializer類中,有一個抽象方法須要實現:ide

public abstract class JsonSerializer<T> implements JsonFormatVisitable {
    ...
    public abstract void serialize(T var1, JsonGenerator var2, SerializerProvider var3) throws IOException, JsonProcessingException;
    ...
}

其中:工具

  • T爲待轉換的數據對象;
  • JsonGenerator主要用於生成目標json,有一系列的方法,如:writeStartObject()writeString()等。(見下參考)
  • SerializerProvider參數暫時可不用。

JsonGenerator參考:測試

  1. Jackson寫入使用JsonGenerator類
  2. jackson中自定義處理序列化和反序列化

JsonGenerator write後的數據,即爲轉化後的數據。示例見下。.net

示例

說明

只有在調用序列化方法後,註解纔會生效。僅僅註解某個元素後,打印結果,該註解並不會生效。

(1) 不使用註解、使用默認序列化

默認序列化,僅使用com.fasterxml.jackson.databind.ObjectMapper下的writeValueAsString(yourEntity),便可序列化。如:

  • entity及測試入口
package jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class CustomDoubleTest {
    
    private Double price;
    private String name;
    
    // getter and setter and toString...

    public static void main(String[] args) {
        CustomDoubleTest t = new CustomDoubleTest();
        t.setPrice(3.14159);
        
        try {
           
            String serialized = new ObjectMapper().writeValueAsString(t);
            System.out.println(serialized);
            
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

bean的默認序列化結果格式:

{"price":"3.14159","name":null}

(2) 使用自定義序列化類

根據標題2.1中所述,使用註解@JsonSerialize時,傳入using參數的類,需實現JsonSerializer

  • 自定義序列化類 CustomDoubleSerialize
/**
 * 將Double類型轉換成保留兩位小數的格式的字符串
 */
public class CustomDoubleSerialize extends JsonSerializer<Double> {
    @Override
    public void serialize(Double aDouble, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        /** jsonGenerator寫後的數據即爲轉換後的數據 */
        jsonGenerator.writeString(new DecimalFormat("##.00").format(aDouble));
        //jsonGenerator.writeString("test");
    }
}
  • entity及測試入口
public class CustomDoubleTest {
    /**
     * 該註解能夠放在字段、getter或setter上
     */
    @JsonSerialize(using = CustomDoubleSerialize.class)
    private Double price;
    private String name;
    
    // 相似上述...
    
     public static void main(String[] args) {
        CustomDoubleTest t = new CustomDoubleTest();
        t.setPrice(3.14159);
        /** 1.直接打印被註解的字段,即便有註解也不起做用 */
        System.out.println("不調用序列化方法即便有註解也不會生效:"+t.getPrice());
        /** 2.直接打印對象,按toString打印。即便有註解也不起做用 */
        System.out.println(t);
        try {
            /** 該方法調用序列化方法,會以json格式展現
             *  1.若是沒有註解,仍然按默認的json格式展現
             *  2.若是有註解(打開註釋),按註解格式展現
             * */
            String serialized = new ObjectMapper().writeValueAsString(t);
            // 3.只有在調用序列化方法時,纔會觸發該註解。
            System.out.println("調用序列化方法後,註解才生效:"+serialized);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

結果:

不調用序列化方法即便有註解也不會生效:3.14159
CustomDoubleTest{price=3.14159, name='null'}
調用序列化方法後,註解才生效:{"price":"3.14","name":null}

(3) 高級序列化

默認的序列化,能夠將複雜的對象按默認格式序列化。如:

public class CustomDoubleTest1 {
    private int id;
    private String name;
    private List<CustomDoubleTest> list;
    private Map<Integer,String> pair;
    private Set<String> set;
    private Boolean flag;
    ...
}

使用默認序列化後:

public static void main(String[] args) {
        CustomDoubleTest1 t = new CustomDoubleTest1();
        // 給對象t賦值
        t.setId(1);
        t.setName("hobe");

        Map pair = new HashMap();
        pair.put(1,"wang");
        pair.put(2,"hong");
        pair.put(3,"bing");
        t.setPair(pair);

        List<CustomDoubleTest> list = new ArrayList<>();
        list.add(new CustomDoubleTest());
        t.setList(list);

        Set<String> set = new HashSet();
        set.add("whbing.cn");
        t.setSet(set);

        t.setFlag(true);

        try {
            /**
             * com.fasterxml.jackson.databind.ObjectMapper
             * 僅一個方法便可【將對象解析成json字符串】
             */
            String serialized = new ObjectMapper().writeValueAsString(t);
            // 只有在調用序列化方法時,纔會觸發該註解。
            System.out.println(serialized);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

將會默認序列化爲如下格式:

{
    "id": 1,
    "name": "hobe",
    "list": [{
        "price": null,
        "name": null
    }],
    "pair": {
        "1": "wang",
        "2": "hong",
        "3": "bing"
    },
    "set": ["whbing.cn"],
    "flag": true
}

對象Map將會以{}包裹,ListSet將會以[]包裹。

高級自定義序列化

參考: jackson中自定義處理序列化和反序列化
  • 自定義序列化類 CustomBeanSerialize
public class CustomBeanSerialize extends JsonSerializer<CustomDoubleTest1> {
    @Override
    public void serialize(CustomDoubleTest1 entity, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeNumberField("id",entity.getId());
        jsonGenerator.writeStringField("mapValue",entity.getList().get(0).getName());
        jsonGenerator.writeEndObject();
    }
}
  • 加上註解後調用序列化方法
@JsonSerialize(using = CustomBeanSerialize.class)
public class CustomDoubleTest1 {
    ...
String serialized = new ObjectMapper().writeValueAsString(t);

顯示結果以下:

{"id":1,"mapValue":null}
相關文章
相關標籤/搜索