1. 依赖
Jackson
库,是基于java语言的开源json格式解析工具。Jackson两大分支codehaus
、fasterxml
。参考: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}
说明:
-
jackson-core
——核心包(必须),提供基于“流模式”解析的API。 -
jackson-databind
——数据绑定包(可选),提供基于“对象绑定”和“树模型”相关API。 -
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 extends JsonSerializer> using() default None.class;
Class extends JsonSerializer> contentUsing() default None.class;
Class extends JsonSerializer> keyUsing() default None.class;
...
说明:
- 该注解存在于运行
RUNTIME
时,可反射获取; - 作用范围可用于类、方法、字段等;
- 通常使用
using
字段,传入格式为继承了JsonSerializer
的类的字节码Class extends JsonSerializer>
。
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
参考:
- Jackson写入使用JsonGenerator类
- 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
将会以{}
包裹,List
和Set
将会以[]包裹。
高级自定义序列化
参考: 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}