博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jackson使用指南
阅读量:7117 次
发布时间:2019-06-28

本文共 13538 字,大约阅读时间需要 45 分钟。

原文链接?

从事JAVA开发工作以来,一直都离不开Jackson的序列化反序列化,对于Jackson的使用也一直处于够用但不深入的状态,下面是日常使用过程中对Jackson的总结。

Jackson常用注解

序列化注解

@JsonAnyGetter

像普通属性一样序列化Map

public class ExtendableBean {    public String name;    private Map
properties; @JsonAnyGetter public Map
getProperties() { return properties; }}复制代码

序列化示例:

{    "name":"My bean",    "attr2":"val2",    "attr1":"val1"}复制代码

@JsonGetter

将指定的方法标记为getter方法。可以用来代替@JsonProperty

public class MyBean {    public int id;    private String name;     @JsonGetter("name")    public String getTheName() {        return name;    }}复制代码

序列化示例:

{    "id": 1,    "name":"My bean"}复制代码

@JsonPropertyOrder

用在类上,在序列化的时候自定义属性输出顺序

@JsonPropertyOrder({ "name", "id" })public class MyBean {    public int id;    public String name;}复制代码

序列化示例:

{    "name":"My bean",    "id": 1}复制代码

@JsonRawValue

完全按照原样序列化属性的值

public class RawBean {    public String name;     @JsonRawValue    public String json;}复制代码

例如:

RawBean bean = new RawBean("My bean", "{\"attr\":false}");复制代码

将序列化为:

{    "name":"My bean",    "json":{        "attr":false    }}复制代码

而不是:

{    "name":"My bean",    "json":"{\"attr\":false}"}复制代码

@JsonValue

定义整个实体的序列化方法,Jackson将会使用该方法的输出作为序列化输出。

public enum TypeEnumWithValue {    TYPE1(1, "Type A"), TYPE2(2, "Type 2");     private Integer id;    private String name;     // standard constructors     @JsonValue    public String getName() {        return name;    }}复制代码

序列化示例:

{  "name": "Type 2"}复制代码

@JsonRootName

如果需要将实体包装一层,可以使用@JsonRootName来指定根包装器的名称

@JsonRootName(value = "user")public class UserWithRoot {    public int id;    public String name;}复制代码

序列化示例:

{    "user": {        "id": 1,        "name": "John"    }}复制代码

如果不用该注解,将会序列化为:

{    "id": 1,    "name": "John"}复制代码

@JsonSerialize

用于指定自定义序列化器来序列化实体

public class Event {    public String name;     @JsonSerialize(using = CustomDateSerializer.class)    public Date eventDate;}复制代码

自定义序列化器如下:

public class CustomDateSerializer extends StdSerializer
{ private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateSerializer() { this(null); } public CustomDateSerializer(Class
t) { super(t); } @Override public void serialize( Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { gen.writeString(formatter.format(value)); }}复制代码

输出示例:

{  "name": "test",  "eventDate": "20-12-2014 02:30:00"}复制代码

反序列化注解

@JsonCreator

指定反序列化使用的构造函数或方法

待反序列化Json示例:

{    "id":1,    "theName":"My bean"}复制代码
public class BeanWithCreator {    public int id;    public String name;     @JsonCreator    public BeanWithCreator(@JsonProperty("id") int id, @JsonProperty("theName") String name) {        this.id = id;        this.name = name;    }}复制代码

@JacksonInject

指定某个字段从注入赋值,而不是从Json

public class BeanWithInject {    @JacksonInject    public int id;         public String name;}复制代码

示例用法:

String json = "{\"name\":\"My bean\"}"; InjectableValues inject = new InjectableValues.Std()  .addValue(int.class, 1);BeanWithInject bean = new ObjectMapper().reader(inject)  .forType(BeanWithInject.class)  .readValue(json);复制代码

@JsonAnySetter

在反序列化时,将Map当成普通属性

待反序列化Json:

{    "name":"My bean",    "attr2":"val2",    "attr1":"val1"}复制代码
public class ExtendableBean {    public String name;    private Map
properties; @JsonAnySetter public void add(String key, String value) { properties.put(key, value); }}复制代码

properties字段的值将会是由 attr2 -> val2,attr1 -> val1组成的键值对。

@JsonSetter

将方法标记为setter方法,可以指定属性名称

public class MyBean {    public int id;    private String name;     @JsonSetter("name")    public void setTheName(String name) {        this.name = name;    }}复制代码

@JsonDeserialize

用于指定自定义反序列化器来反序列化实体

public class Event {    public String name;     @JsonDeserialize(using = CustomDateDeserializer.class)    public Date eventDate;}复制代码

对应的反序列化器:

public class CustomDateDeserializer  extends StdDeserializer
{ private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateDeserializer() { this(null); } public CustomDateDeserializer(Class
vc) { super(vc); } @Override public Date deserialize( JsonParser jsonparser, DeserializationContext context) throws IOException { String date = jsonparser.getText(); try { return formatter.parse(date); } catch (ParseException e) { throw new RuntimeException(e); } }}复制代码

Jackson设置属性是否参与序列化

@JsonIgnoreProperties

在类上指定要忽略的属性

@JsonIgnoreProperties({ "id" })public class BeanWithIgnore {    public int id;    public String name;}复制代码

@JsonIgnore

在具体属性上忽略,使其不参与序列化过程

public class BeanWithIgnore {    @JsonIgnore    public int id;     public String name;}复制代码

@JsonIgnoreProperties是等效的。

@JsonIgnoreType

用在类上,将忽略该类所有属性

public class User {    public int id;    public Name name;     @JsonIgnoreType    public static class Name {        public String firstName;        public String lastName;    }}复制代码

@JsonInclude

用于排除值为empty/null/default的属性

@JsonInclude(Include.NON_NULL)public class MyBean {    public int id;    public String name;}复制代码

@JsonAutoDetect

强制序列化私有属性,不管它有没有getter方法

@JsonAutoDetect(fieldVisibility = Visibility.ANY)public class PrivateBean {    private int id;    private String name;}复制代码

Jackson处理多态

一般都是组合起来使用,有下面三个注解:

  • @JsonTypeInfo

指定序列化中包含的类型信息的详细信息

  • @JsonSubTypes

指定带注释类型的子类型

  • @JsonTypeName

指定用于带注释的类的逻辑类型名称

public class Zoo {    public Animal animal;     @JsonTypeInfo(      use = JsonTypeInfo.Id.NAME,       include = As.PROPERTY,       property = "type")    @JsonSubTypes({        @JsonSubTypes.Type(value = Dog.class, name = "dog"),        @JsonSubTypes.Type(value = Cat.class, name = "cat")    })    public static class Animal {        public String name;    }     @JsonTypeName("dog")    public static class Dog extends Animal {        public double barkVolume;    }     @JsonTypeName("cat")    public static class Cat extends Animal {        boolean likesCream;        public int lives;    }}复制代码

上述例子中,指定属性type为判断具体子类的依据,例如:type=dog,将被序列化为Dog类型。

Jackson通用注解(序列化反序列化都生效)

@JsonProperty

指定JSON中的属性名称

public class MyBean {    public int id;    private String name;     @JsonProperty("name")    public void setTheName(String name) {        this.name = name;    }     @JsonProperty("name")    public String getTheName() {        return name;    }}复制代码

@JsonFormat

用于在序列化日期/时间值时指定格式。

public class Event {    public String name;     @JsonFormat(      shape = JsonFormat.Shape.STRING,      pattern = "dd-MM-yyyy hh:mm:ss")    public Date eventDate;}复制代码

@JsonUnwrapped

将对象中所有的属性与当前平级,不太好描述,简单说就是拆开包装。

public class UnwrappedUser {    public int id;     @JsonUnwrapped    public Name name;     public static class Name {        public String firstName;        public String lastName;    }}复制代码

序列化示例:

{    "id":1,    "firstName":"John",    "lastName":"Doe"}复制代码

如果不加@JsonUnwrapped注解,将被序列化为:

{    "id":1,    "name": {        "firstName":"John",        "lastName":"Doe"    }}复制代码

@JsonView

指定视图,类似分组进行序列化/反序列化

定义视图:

public class Views {    public static class Public {}    public static class Internal extends Public {}}复制代码

定义实体:

public class Item {    @JsonView(Views.Public.class)    public int id;     @JsonView(Views.Public.class)    public String itemName;     @JsonView(Views.Internal.class)    public String ownerName;}复制代码

序列化示例:

String result = new ObjectMapper()  .writerWithView(Views.Public.class)  .writeValueAsString(item);复制代码

这时,将只会序列化iditemName字段

@JsonManagedReference, @JsonBackReference

@JsonManagedReference和@JsonBackReference注释用于处理父/子关系并解决循环问题。

例如,有两个相互引用的类:

public class ItemWithRef {    public int id;    public String itemName;     @JsonManagedReference    public UserWithRef owner;}复制代码
public class UserWithRef {    public int id;    public String name;     @JsonBackReference    public List
userItems;}复制代码

不加注解,会循环调用,导致内存溢出,这时候可以使用@JsonManagedReference@JsonBackReference来避免内存溢出。

@JsonIdentityInfo

用于指定在序列化/反序列化值时使用对象标识,例如,处理无限递归类型的问题。

@JsonIdentityInfo(  generator = ObjectIdGenerators.PropertyGenerator.class,  property = "id")public class ItemWithIdentity {    public int id;    public String itemName;    public UserWithIdentity owner;}复制代码

@JsonFilter

指定序列化期间要使用的过滤器。

@JsonFilter("myFilter")public class BeanWithFilter {    public int id;    public String name;}复制代码

示例代码:

BeanWithFilter bean = new BeanWithFilter(1, "My bean");FilterProvider filters   = new SimpleFilterProvider().addFilter(    "myFilter",     SimpleBeanPropertyFilter.filterOutAllExcept("name"));String result = new ObjectMapper()  .writer(filters)  .writeValueAsString(bean);复制代码

自定义Jackson注解

可以使用@JacksonAnnotationsInside来开发自定义注解

@Retention(RetentionPolicy.RUNTIME)    @JacksonAnnotationsInside    @JsonInclude(Include.NON_NULL)    @JsonPropertyOrder({ "name", "id", "dateCreated" })    public @interface CustomAnnotation {}复制代码

如何使用自定义注解:

@CustomAnnotationpublic class BeanWithCustomAnnotation {    public int id;    public String name;    public Date dateCreated;}复制代码

自定义注解可以增强代码复用,把一些通用的Jackson注解组合起来,形成一个新注解,新注解可以代替组合的注解。

Jackson MixIn 注解

动态地为某些类型增加统一的Jackson注解

实体:

public class Item {    public int id;    public String itemName;    public User owner;}复制代码

MixIn类:

@JsonIgnoreTypepublic class MyMixInForIgnoreType {}复制代码

我们可以动态地让User类型不参与序列化:

Item item = new Item(1, "book", null);ObjectMapper mapper = new ObjectMapper();mapper.addMixIn(User.class, MyMixInForIgnoreType.class);result = mapper.writeValueAsString(item);复制代码

禁用Jackson注解

假设我们有一个带Jackson注解的实体:

@JsonInclude(Include.NON_NULL)@JsonPropertyOrder({ "name", "id" })public class MyBean {    public int id;    public String name;}复制代码

我们可以这样来禁用该实体上的所有Jackson注解:

MyBean bean = new MyBean(1, null);ObjectMapper mapper = new ObjectMapper();mapper.disable(MapperFeature.USE_ANNOTATIONS);复制代码

Jackson的ObjectMapper用法

java类 转换为 json

可以直接序列化为Json字符串:

objectMapper.writeValueAsString(car);复制代码

或者,可以序列化到文件,文件内容是Json字符串:

objectMapper.writeValue(new File("target/car.json"), car);复制代码

json 转换为 java类

从字符串:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";objectMapper.readValue(json, Car.class); 复制代码

从文件:

objectMapper.readValue(new File("target/json_car.json"), Car.class);复制代码

从URL:

objectMapper.readValue(new URL("target/json_car.json"), Car.class);复制代码

json转换为Jackson JsonNode

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";JsonNode jsonNode = objectMapper.readTree(json);String color = jsonNode.get("color").asText();// Output: color -> Black复制代码

json 转换为 java集合

String jsonCarArray =   "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";List
listCar = objectMapper.readValue(jsonCarArray, new TypeReference
>(){});复制代码

json 转换为 Map

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";Map
map = objectMapper.readValue(json, new TypeReference
>(){});复制代码

ObjectMapper的常用配置

忽略不识别的字段(json属性与目标实体存在属性上的差异):

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);复制代码

允许原始值为null:

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);复制代码

允许将枚举序列化/反序列化为数字:

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);复制代码

配置自定义序列化/反序列化器

假设有一个序列化器:

public class CustomCarSerializer extends StdSerializer
{ public CustomCarSerializer() { this(null); } public CustomCarSerializer(Class
t) { super(t); } @Override public void serialize( Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("car_brand", car.getType()); jsonGenerator.writeEndObject(); }}复制代码

一个反序列化器:

public class CustomCarDeserializer extends StdDeserializer
{ public CustomCarDeserializer() { this(null); } public CustomCarDeserializer(Class
vc) { super(vc); } @Override public Car deserialize(JsonParser parser, DeserializationContext deserializer) { Car car = new Car(); ObjectCodec codec = parser.getCodec(); JsonNode node = codec.readTree(parser); // try catch block JsonNode colorNode = node.get("color"); String color = colorNode.asText(); car.setColor(color); return car; }}复制代码

ObjectMapper使用他们:

//添加自定义序列化器module.addSerializer(Car.class, new CustomCarSerializer());//添加自定义反序列化器module.addDeserializer(Car.class, new CustomCarDeserializer());复制代码

处理日期格式化

ObjectMapper objectMapper = new ObjectMapper();DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");objectMapper.setDateFormat(df);复制代码

处理集合

反序列化为数组:

String jsonCarArray =   "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);复制代码

反序列化为集合:

String jsonCarArray =   "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";ObjectMapper objectMapper = new ObjectMapper();List
listCar = objectMapper.readValue(jsonCarArray, new TypeReference
>(){});复制代码

? ?

转载于:https://juejin.im/post/5c4970c6e51d4551b7482487

你可能感兴趣的文章
JS复习之数据类型
查看>>
给DataTable中添加一行数据
查看>>
linux nadianshi
查看>>
Java 的静态代理 动态代理(JDK和cglib)
查看>>
【转载】Express、Koa、Hapi框架对比
查看>>
hdu 5111 树上求交
查看>>
ubuntu server 安装 mantis bug tracker 中文配置
查看>>
HTTP请求415错误 – 不支持的媒体类型(Unsupported media type)
查看>>
W驱开技详.问题解决
查看>>
数据结构复习之链表
查看>>
[Asp.net]AspNetPager分页组件
查看>>
[JVM-4]Java内存模型(JMM)
查看>>
numpy 的三角函数运算
查看>>
二分查找及其变种简单易懂的模版
查看>>
mysql优化小技巧
查看>>
CardinalSpline样条曲线(沿着正方形路线走)
查看>>
设计模式之观察者设计模式
查看>>
HDOJ_ACM_Bone Collector
查看>>
第三章:垃圾回收器:垃圾回收器的两种算法
查看>>
力扣算法题—091解码
查看>>