Jackson常用注解详解1 初级2 中级

1 初级

我们从几个简单的使用场景开始:重命名属性,忽略属性,以及修改属性所使用的类型。

  • 注意 下面的例子仅仅显示了成员属性,注解同样也可以用在成员方法(getter/setter)上

①属性重命名时使用的注解

最常见的使用方式之一就是改变某个成员属性所使用的JSON名称,例如:

public class Name { 

  @JsonProperty("firstName") 
  public String _first_name; 
} 

将会生成如下所示的JSON数据结果:

{ "firstName" : "Bob" } 

而不是:

{ "_first_name" : "Bob"} 

②忽略属性时使用的注解

有时POJO包括了一些你不希望输出的属性,在这种情况下,你可以进行如下操作:

public class Value { 

  public int value; 

  @JsonIgnore 
  public int internalValue; 
} 

这时得到的JSON数据结果如下:

{ "value" : 42 } 

或者,你可能忽略掉某些从JSON数据中得到的属性,如果是这样,你可以使用:

@JsonIgnoreProperties({ "extra", "uselessValue" }) 
public class Value { 
  public int value; 
} 

这样就能够处理像如下所示的JSON数据:

{   
    "value" : 42,
    "extra" : "fluffy",
    "uselessValue" : -13
 } 

最后,你甚至能简单地忽略掉从JSON(由于在应用中没有完全匹配的POJO)中获得的所有“多余的”属性。你可以通过添加如下代码完成这个操作:

@JsonIgnoreProperties(ignoreUnknown=true) 
public class PojoWithAny { 
  public int value; 
} 

③选择更多/更少指定类型时使用的注解

在有些情况下,Jackson在读入或输出一个成员属性时,所选用的类型可能并不是你想要的:

  • 当读取(反序列化)时,声明的类型可能是一个基本类型,但是你确切地知道应该使用的实现类型(ps:也就说,我们需要反序列化后生成的对象是实现类型的)
  • 当输出(序列化)时,Jackson默认使用的是给定的运行时类型;但是你可能不想输出那个类型的所有信息,而仅仅是它的父类型所囊括的信息。

在这些应用场景,你可以使用如下的注解进行处理:

public class ValueContainer { 
  // 虽然代码中使用的类型是 Value, 但我们希望读取到的JSON 之后得到的对象的类型是 ValueImpl 
  @JsonDeserialize(as=ValueImpl.class) 
  public Value value; 

  // 虽然运行时的类型可能是 AdvancedType , 但是我们确实想序列化 
  // 成为 BasicType ; 有两种处理方式: 
  @JsonSerialize(as=BasicType.class) 
  // 或者我们可以这样: @JsonSerialize(typing=Typing.STATIC) 
  public BasicType another; 
} 

2 中级

①使用构造器或工厂方法

在默认情况下,当由JSON数据创建相应类的实例时,Jackson尝试使用该类的“默认”构造器(即无参数构造器)。 不过,你可以选择使用其他的构造器,或者一个静态工厂方法,来创建实例。 完成这个操作,你需要使用@JsonCreator,有可能还需要使用@JsonProperty给参数绑定名称

public class CtorPOJO { 
   private final int _x, _y; 

   @JsonCreator 
   public CtorPOJO(@JsonProperty("x") int x, @JsonProperty("y") int y) { 
      _x = x; 
      _y = y; 
   } 
} 

使用相同的方式,可以将@JsonCreator用在静态工厂方法上。 不过,还有一个可选的替代方案,被称作“授权式”构建器(“delegating” creator):

public class DelegatingPOJO { 
   private final int _x, _y; 

   @JsonCreator 
   public DelegatingPOJO(Map<String,Object> delegate) { 
      _x = (Integer) delegate.get("x"); 
      _y = (Integer) delegate.get("y"); 
   } 
} 

不同之处在于,构建器方法只能有一个参数,而且参数禁止添加@JsonProperty注解。

②处理多态类型(polymorphic types)

如果你要进行读取、输出操作的对象拥有许多可能的子类型(即表现出多态性),你可能还需要添加一些类型信息。Jackson在反序列化时(读取JSON数据,生成相应的对象)需要这些信息,以便能正确地读取对象的类型。我们可以通过在“基本类型”上添加@JsonTypeInfo注解来完成操作:

//将Java类的名称(“com.myempl.ImplClass”)存储到JSON的一个名称为“class”的属性中 
@JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY,property=”class”) 
public abstract class BaseClass { 
} 

public class Impl1 extends BaseClass { 
  public int x; 
} 

public class Impl2 extends BaseClass { 
  public String name; 
 } 

public class PojoWithTypedObjects { 
  public List<BaseClass> items; 
} 

这样,序列化之后的JSON格式如下:

{
  “items” : [ 
      {
        “class”:”Impl2”,
        “name”: “Bob”
      }, 
      {
        “class”:”Impl1”,
        ”x” : 13
      } 
]} 
  • 注意 这个注解还有很多配置可以进行设置,详细内容请查阅浏览:
    • Javadocs
    • 多态类型处理简介I(ntro to polymorphic type handling)

③重新设置属性的自动发现(Changing property auto-detection)

Jackson默认的属性发现规则将会查找到如下所述的属性:

  • 所有被public修饰的字段(成员变量);
  • 所有被public修饰的getter(即形如“getXxx()”的方法);
  • 所有被public修饰的setter(即形如“setXxx(value)”的方法),不管可见或不可见。 不过如果这样也不行,你可以通过使用使用@JsonAutoDetect来改变可见级别。 如果你想自动发现所有的字段(就像GSON包所进行的操作那样),你可以这样做:
@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) 
public class POJOWithFields { 
  private int value; 
} 

或者,你想禁用对所有字段的自动发现:

@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE) 
public class POJOWithNoFields { 
  //不会被序列化,除非再有一个可以访问的“getValue”方法 
  public int value; 
} 

拓展阅读

  • 列举出的所有可用的Jackson注解
  • 文档

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP实战技术

PHP垃圾回收机制

PHP垃圾回收机制 1、每一个变量定义时都保存在一个叫zval的容器里面,这里面包含了数量的类型和和值,还包含了一个refcount(理解为存在几个变量个数)和...

34540
来自专栏非著名程序员

Java 反射基础(下)

? 投稿作者:芮成兵/csdn 原文链接: http://blog.csdn.net/My_TrueLove/article/details/51306921...

26460
来自专栏机器学习和数学

[编程经验]python2和python3的区别总结

最近涨粉涨的厉害啊,那天看刚破800,今天打开又有32个新粉丝,有点开心,哈哈哈。说实话,看的人多的话,是我坚持下去最大的动力。。。 = = = print("...

32840
来自专栏IT探索

g++&&gcc

3.C++:在构造函数中,当使用初始化列表来初始化成员变量时,如果初始化顺序与定义成员变量的顺序不一致,当使用-Wreorder选项时,会重新调整顺序初始化顺序...

8210
来自专栏前端侠2.0

atob和btoa的趣谈 原

不了解的人突然看到window对象的atob和btoa 函数,估计会认为哪个臭小子添加全局函数了。

17720
来自专栏Java后端技术栈

如何在你的项目中使用JSR 303 - Bean Validation进行数值校验?

JSR-303 是 Java EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是hibernate Validator。

24340
来自专栏java一日一条

一个Java对象到底占用多大内存

大家可以用这个代码边看边验证,注意的是,运行这个程序需要通过javaagent注入Instrumentation,具体可以看原博客。我今天主要是总结下手动计算J...

9810
来自专栏信安之路

利用Java反射和类加载机制绕过JSP后门检测

JSP 后门,一般是指文件名以 .jsp 等后缀结尾的,可运行于 Java servlet 及相关容器和组件内的通用 JSP 脚本。

38100
来自专栏郭少华

ES6

在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。

19030
来自专栏博岩Java大讲堂

Java虚拟机--你的对象有多大如何计算对象大小

47150

扫码关注云+社区

领取腾讯云代金券