jackson 序列化相关注解与配置

配置

忽略不认识的字段

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

这样是配置在整个ObjectMapper上的,如果只希望配置在某个类上面,可以使用@JsonIgnoreProperties(ignoreUnknown=true)

注解使用

忽略NULL字段

实体类上使用
// 过NULL字段,但是过期了
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
// 现在推荐使用该方式
@JsonInclude(JsonInclude.Include.NON_NULL)

如果使用在类上,那么对该类中的所有字段都起作用
如果只使用到某个字段上,那么只是对该字段起作用

参数意义:
JsonInclude.Include.ALWAYS 默认

JsonInclude.Include.NON_DEFAULT 属性为默认值不序列化

JsonInclude.Include.NON_EMPTY 属性为 空(””) 或者为 NULL 都不序列化

JsonInclude.Include.NON_NULL 属性为NULL 不序列化

配置文件中

这里以springboot为例,在yml中配置全局定义

spring:
   jackson:
        default-property-inclusion: non_null

忽略序列化

json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。

// 此注解用于属性或者方法上(最好是属性上)
@JsonIgnore
// 此注解是类注解, 在此指定忽略name,age字段
@JsonIgnoreProperties({"name"},{"age"})
public class  user {
    private String name;
    private int age;
    private String address;
}

引用同一个对象

我们看个简单的例子,有两个类Common和A,A中有两个Common对象,如下:

static class Common {
    public String name;
}
static class A {
    public Common first;
    public Common second;
}

现在新建一个对象A和Common,将first和second都指向同一个common

Common c = new Common();
c.name = "common";
A a = new A();
a.first = a.second = c

此时使用jackson序列化a后输入为

{
    "first": {
        "name": "common"
    },
    "second": {
        "name": "common"
    }
}

但是在反序列化后,first和second将指向不同的对象。
此时可以使用注解@JsonIdentityInfo

解决循环引用

假设有一个Parent类和一个Child类,它们相互引用

static class Parent {
    public String name;
    public Child child;
}
static class Child {
    public String name;
    public Parent parent;
}

相互引用如下

Parent p = new Parent();
p.name = "父亲";
Chilc c = new Child();
c.name = "儿子";
p.child = c;
c.parent = p;

如果用jackson序列化p这个对象,jackson会进入无限循环最终抛出异常。
解决这个问题,可以分别标记Parent类中的child和Child类中的parent字段,将其中一个标记为主引用,另一个标记为反向引用,主引用用@JsonManagedReference,反向引用使用@JsonBackReference

继承和多态

Jackson不能自动处理多态的情况。

static class Shape {} 

static class Circle extends Shape {
    private int r;
}

static class Square extends Shape {
    private int l;
}

static class ShapeManager {
    private List<Shape> shapes;
}

ShapeManager中的Shape列表中的对象可能是Circle,也可能是Square。如:

ShapeManager sm = new ShapeManager();
List<Shape> shapes = new ArrayList<Shape>();
shapes.add(new Circle(10));
shapes.add(new Square(5));
sm.setShapes(shapes);

此时将sm序列化输出为:

{
    "shapes":[{
        "r": 10
    }, {
        "l": 5
    }]
}

这个输出看上去是没有问题的,但是由于输出中没有类型信息,反序列化时,Jackson不知道具体的Shape类型是什么,就会抛出异常。

解决办法就是在输出中包含类型信息,在基类Shape前使用如下注解:

@JsonTypeInfo(use = ID.NAME, include = As.PROPERTY, property = "TYPE")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Circle.class, name="circle"),
    @JsonSubTypes.Type(value = Square.class, name="square")})
static class Shape {

}   

含义是在输出中增加属性”type”,表示对象的实际类型,对Circle类,使用”circle”表示其类型,而对Square类,使用”square”。加了注解后,序列化输出变成:

{
    "shapes":[{
        "type": "circle",
        "r": 10
    }, {
        "type": "square",
        "l": 5
    }]
}

修改字段名

如果我们希望输出的字段名变为对应的中文

public class Student {
    @JsonProperty("姓名");
    String name;
}

日期时间格式化

@JsonSerialize(using = Date2LongSerializer.class)

java中JsonSerializer用法,前后端单位转换必备

@JsonFormat(pattern="yyyy-MM-dd HH:mm", timezone="GMT+8")  
private Date regisDate; 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值