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

1. 依赖

Jackson库,是基于java语言的开源json格式解析工具。Jackson两大分支codehausfasterxml。参考:Jackson两大分支codehaus、fasterxml的区别
Jackson从2.0开始改用新的包名fasterxml,1.x版本的包名是codehaus。如果是新项目,建议直接用2x,即fasterxml jackson
整个库包含3个jar包:



    com.fasterxml.jackson.core
    jackson-core
    
    ${dependency.version.jackson}


    com.fasterxml.jackson.core
    jackson-databind
    ${dependency.version.jackson}


    com.fasterxml.jackson.core
    jackson-annotations
    ${dependency.version.jackson}


说明

  1. jackson-core——核心包(必须),提供基于“流模式”解析的API。
  2. jackson-databind——数据绑定包(可选),提供基于“对象绑定”和“树模型”相关API。
  3. jackson-annotations——注解包(可选),提供注解功能。

其他

在时候用mybatis时,还有以下包,用于映射LocalDateTime与数据库中的time:


   org.mybatis
   mybatis-typehandlers-jsr310


   com.fasterxml.jackson.datatype
   jackson-datatype-jsr310

2. 典型注解

1) @JsonSerialize

该注解部分源码如下:

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 using() default None.class;

    Class contentUsing() default None.class;

    Class keyUsing() default None.class;

    ...

说明

  • 该注解存在于运行RUNTIME时,可反射获取;
  • 作用范围可用于类、方法、字段等;
  • 通常使用using字段,传入格式为继承了JsonSerializer的类的字节码Class

JsonSerializer类中,有一个抽象方法需要实现:

public abstract class JsonSerializer 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后的数据,即为转化后的数据。示例见下。

示例

说明

只有在调用序列化方法后,注解才会生效。仅仅注解某个元素后,打印结果,该注解并不会生效。

(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 {
    @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 list;
    private Map pair;
    private Set 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 list = new ArrayList<>();
        list.add(new CustomDoubleTest());
        t.setList(list);

        Set 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 {
    @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}

你可能感兴趣的:(jackson)