java 注解不能序列化方法_jackson解析之(1)注解序列化

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 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将会以[]包裹。

高级自定义序列化

自定义序列化类 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}

你可能感兴趣的:(java,注解不能序列化方法)