jackson注解使用

读 + 写 注解

@JsonIgnore

在将Java对象序列化为json时,有些属性需要过滤掉,不显示在json中,可以使用@JsonIgnore忽略单个字段。

public class PersonIgnore {
    @JsonIgnore
    public long    personId = 0;
    public String  name = null;
}

@JsonIgnoreProperties

作用于类,表示被注解该类型的属性将不会被序列化和反序列化

@Test  
public void jsonFilter() throws Exception {  
    TestPOJO testPOJO = new TestPOJO();  
    testPOJO.setName("myName");  
    Sub1 sub1 = new Sub1();  
    sub1.setId(1);  
    sub1.setName("sub1");  
    Sub2 sub2 = new Sub2();  
    sub2.setId(2);  
    sub2.setAge(22);  
    testPOJO.setMyIn(sub1);  
    testPOJO.setSub1(sub1);  
    testPOJO.setSub2(sub2);  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = objectMapper.writeValueAsString(testPOJO);  
    System.out.println(jsonStr);  
}  
  
public static class TestPOJO{  
    private Sub1 sub1;  
    private Sub2 sub2;  
    private MyIn myIn;  
    private String name;  
    //getters、setters省略  
}  
  
public static class MyIn{  
    private int id;  
    //getters、setters省略  
}  
  
@JsonIgnoreType  
public static class Sub1 extends MyIn{  
    private String name;  
    //getters、setters省略  
}  
  
@JsonIgnoreType  
public static class Sub2 extends MyIn{  
    private int age;  
    //getters、setters省略  
} 

上面例子中我们在类Sub1和Sub2上都加上了@JsonIgnoreType,那么需要序列化和反序列时POJO中所有Sub1和Sub2类型的属性都将会被忽略,上面测试结果为{“myIn”:{“id”:1,“name”:“sub1”},“name”:“myName”},只输出了name和myIn属性。需要注意的是@JsonIgnoreType是可以继承的,即如果在基类上添加了该注解,那么子类也相当于加了该注解。在上例中,如果只在基类MyIn上添加@JsonIgnoreType那么序列化TestPOJO时将会过滤掉MyIn、Sub1、Sub2。输出结果为{“name”:“myName”}

@JsonAutoDetect

开启/禁止自动检测

fieldVisibility:字段的可见级别

ANY:任何级别的字段都可以自动识别

NONE:所有字段都不可以自动识别

NON_PRIVATE:非private修饰的字段可以自动识别

PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被自动识别

PUBLIC_ONLY:只有被public修饰的字段才可以被自动识别

DEFAULT:同PUBLIC_ONLY

jackson默认的字段属性发现规则如下:

所有被public修饰的字段->所有被public修饰的getter->所有被public修饰的setter
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY )
public class PersonAutoDetect {

    private long  personId = 123;
    public String name     = null;

}

这个类我们没有提供对应的get,set方法,如果按照默认的属性发现规则我们将无法序列化和反序列化personId字段(如果没有get,set方法,只有被public修饰的属性才会被发现),你可以通过修改@JsonAutoDetect的fieldVisibility来调整自动发现级别,为了使name被自动发现,我们需要将级别调整为ANY

@JsonProperty

作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名,比如在很多场景下Java对象的属性是按照规范的驼峰书写,但是实际展示的却是类似C-style或C++/Microsolft style

@Test  
public void jsonPropertyTest() throws Exception {  
    TestPOJO testPOJO = new TestPOJO();  
    testPOJO.wahaha(111);  
    testPOJO.setFirstName("myName");  
  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = objectMapper.writeValueAsString(testPOJO);  
    Assert.assertEquals("{\"id\":111,\"first_name\":\"myName\"}",jsonStr);  
  
    String jsonStr2 = "{\"id\":111,\"first_name\":\"myName\"}";  
    TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2, TestPOJO.class);  
    Assert.assertEquals(111, testPOJO2.wahaha());  
    Assert.assertEquals("myName", testPOJO2.getFirstName());  
}  
  
public static class TestPOJO{  
    @JsonProperty//注意这里必须得有该注解,因为没有提供对应的getId和setId函数,而是其他的getter和setter,防止遗漏该属性  
    private int id;  
    @JsonProperty("first_name")  
    private String firstName;  
  
    public int wahaha() {  
        return id;  
    }  
  
    public void wahaha(int id) {  
        this.id = id;  
    }  
  
    public String getFirstName() {  
        return firstName;  
    }  
  
    public void setFirstName(String firstName) {  
        this.firstName = firstName;  
    }  
}  

@JsonUnwrapped

作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象,说起来比较难懂,看个例子就很清楚了,不多解释

@Test  
public void jsonUnwrapped() throws Exception {  
    TestPOJO testPOJO = new TestPOJO();  
    testPOJO.setId(111);  
    TestName testName = new TestName();  
    testName.setFirstName("张");  
    testName.setSecondName("三");  
    testPOJO.setName(testName);  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = objectMapper.writeValueAsString(testPOJO);  
    //如果没有@JsonUnwrapped,序列化后将为{"id":111,"name":{"firstName":"张","secondName":"三"}}  
    //因为在name属性上加了@JsonUnwrapped,所以name的子属性firstName和secondName将不会包含在name中。  
    Assert.assertEquals("{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}",jsonStr);  
    String jsonStr2 = "{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}";  
    TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);  
    Assert.assertEquals(111,testPOJO2.getId());  
    Assert.assertEquals("张",testPOJO2.getName().getFirstName());  
    Assert.assertEquals("三",testPOJO2.getName().getSecondName());  
}  
  
public static class TestPOJO{  
    private int id;  
    @JsonUnwrapped  
    private TestName name;  
  
    //getters、setters省略  
}                                                                                                                             public static class TestName{  
    private String firstName;  
    private String secondName;  
  
    //getters、setters省略  
}  

在2.0+版本中@JsonUnwrapped添加了prefix和suffix属性,用来对字段添加前后缀,这在有关属性分组上比较有用,在上面的测试用例中,如果我们将TestPOJO的name属性上的@JsonUnwrapped添加前后缀配置,即

@JsonUnwrapped(prefix = "name_",suffix = "_test")  

那么TestPOJO序列化后将为{“id”:111,“name_firstName_test”:“张”,“name_secondName_test”:“三”},反序列化时也要加上前后缀才会被解析为POJO

@JsonRootName

使用在类上,标注为该类在转换为json string的时候,需要新增一个根节点rootNode

@JsonRootName("myPojo")  
public static class TestPOJO{  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}  

该类在序列化成json后类似如下:{“myPojo”:{“name”:“aaaa”}}

读 注解

@JsonAnySetter

作用于方法,在反序列化时用来处理遇到未知的属性的时候调用,@JsonAnySetter和map属性配合使用用来保存未知的属性

@Test  
public void jsonAnySetter() throws Exception {  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = "{\"name\":\"myName\",\"code\":\"12345\",\"age\":12}";  
    TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);  
    Assert.assertEquals("myName",testPOJO.getName());  
    Assert.assertEquals("12345",testPOJO.getOther().get("code"));  
    Assert.assertEquals(12,testPOJO.getOther().get("age"));  
}  
  
public static class TestPOJO{  
    private String name;  
  
    private Map other = new HashMap();  
  
    @JsonAnySetter  
    public void set(String name,Object value) {  
        other.put(name,value);  
    }  
  
    //getters、setters省略  
} 

@JsonCreator

作用于方法,通常用来标注构造方法或静态工厂方法上,使用该方法来构建实例,默认的是使用无参的构造方法,通常是和@JsonProperty@JacksonInject配合使用

@Test  
public void jsonCreator() throws Exception {  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = "{\"full_name\":\"myName\",\"age\":12}";  
    TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);  
    Assert.assertEquals("myName",testPOJO.getName());  
    Assert.assertEquals(12, testPOJO.getAge());  
}  
  
public static class TestPOJO{  
    private String name;  
    private int age;  
  
    @JsonCreator  
    public TestPOJO(@JsonProperty("full_name") String name,@JsonProperty("age") int age){  
        this.name = name;  
        this.age = age;  
    }  
    public String getName() {  
        return name;  
    }  
    public int getAge() {  
        return age;  
    }  
}  

上面示例中是在构造方法上标注了@JsonCreator,同样你也可以标注在静态工厂方法上,比如:

@Test  
public void jsonCreator() throws Exception {  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = "{\"name\":\"myName\",\"birthday\":1416299461556}";  
    TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);  
    Assert.assertEquals("myName",testPOJO.getName());  
    System.out.println(testPOJO.getBirthday());  
}  
  
public static class TestPOJO{  
    private String name;  
    private Date birthday;  
  
    private TestPOJO(String name,Date birthday){  
        this.name = name;  
        this.birthday = birthday;  
    }  
  
    @JsonCreator  
    public static TestPOJO getInstance(@JsonProperty("name") String name,@JsonProperty("birthday") long timestamp){  
        Date date = new Date(timestamp);  
        return new TestPOJO(name,date);  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public Date getBirthday() {  
        return birthday;  
    }  
}  

这个实例中,TestPOJO的构造方法是私有的,外面无法new出来该对象,只能通过工厂方法getInstance来构造实例,此时@JsonCreator就标注在工厂方法上。

除了这2种方式外,还有一种构造方式成为授权式构造器,也是我们平常比较常用到的,这个构造器只有一个参数,且不能使用@JsonProperty

@Test  
public void jsonCreator() throws Exception {  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = "{\"full_name\":\"myName\",\"age\":12}";  
    TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);  
    Assert.assertEquals("myName",testPOJO.getName());  
    Assert.assertEquals(12,testPOJO.getAge());  
}  
  
public static class TestPOJO{  
    private String name;  
    private int age;  
    @JsonCreator  
    public TestPOJO(Map map){  
        this.name = (String)map.get("full_name");  
        this.age = (Integer)map.get("age");  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
}  

@JacksonInject

作用于属性、方法、构造参数上,被用来反序列化时标记已经被注入的属性。

@Test  
public void jacksonInject() throws Exception {  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = "{\"age\":12}";  
    InjectableValues inject = new InjectableValues.Std().addValue("name","myName");  
    TestPOJO testPOJO = objectMapper.reader(TestPOJO.class).with(inject).readValue(jsonStr);  
    Assert.assertEquals("myName", testPOJO.getName());  
    Assert.assertEquals(12,testPOJO.getAge());  
}  
  
public static class TestPOJO{  
    @JacksonInject("name")  
    private String name;  
    private int age;  
  
    //getters、setters省略  
}  

@JsonDeserialize

作用于方法和字段上,通过using(JsonDeserializer)来指定反序列化的实现,通常我们在需要自定义反序列化时会用到,比如下面的例子中的日期转换

@Test  
public void jsonSerializeAndDeSerialize() throws Exception {  
    TestPOJO testPOJO = new TestPOJO();  
    testPOJO.setName("myName");  
    testPOJO.setBirthday(new Date());  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = objectMapper.writeValueAsString(testPOJO);  
    System.out.println(jsonStr);  
  
    String jsonStr2 = "{\"name\":\"myName\",\"birthday\":\"2014-11-11 19:01:58\"}";  
    TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);  
    System.out.println(testPOJO2.toString());  
}  
public static class TestPOJO{  
    private String name;  
    @JsonDeserialize(using = MyDateDeserializer.class)  
    private Date birthday;  
  
    //getters、setters省略  
  
    @Override  
    public String toString() {  
        return "TestPOJO{" +  
            "name='" + name + '\'' +  
            ", birthday=" + birthday +  
            '}';  
    }  
}  
private static class MyDateDeserializer extends JsonDeserializer<Date>{  
    @Override  
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {  
        String value = jp.getValueAsString();  
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        try {  
            return dateFormat.parse(value);  
        } catch (ParseException e) {  
            e.printStackTrace();  
        }  
        return null;  
    }  
} 

写 注解

@JsonInclude

是用再实体类的方法类的头上 作用是实体类的参数查询到的为null的不显示

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PersonInclude {

    public long  personId = 0;
    public String name     = null;

}

@JsonAnyGetter

@JsonAnyGetter相反

public class PersonAnyGetter {

    private Map<String, Object> properties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> properties() {
        return properties;
    }
}

@JsonPropertyOrder

作用在类上,被用来指明当序列化时需要对属性做排序,它有2个属性
一个是alphabetic:布尔类型,表示是否采用字母拼音顺序排序,默认是为false,即不排序

@Test  
public void jsonPropertyOrder() throws Exception {  
    TestPOJO testPOJO = new TestPOJO();  
    testPOJO.setA("1");  
    testPOJO.setB("2");  
    testPOJO.setC("3");  
    testPOJO.setD("4");  
    ObjectMapper objectMapper = new ObjectMapper();  
    String jsonStr = objectMapper.writeValueAsString(testPOJO);  
    System.out.println(jsonStr);  
    Assert.assertEquals("{\"c\":\"3\",\"b\":\"2\",\"a\":\"1\",\"d\":\"4\"}",jsonStr);  
}  
  
@JsonPropertyOrder(alphabetic = true,value = {"c","b"})  
public static class TestPOJO{  
    private String a;  
    private String c;  
    private String d;  
    private String b;  
  
    //getters、setters省略  
}  

上面例子可以看到value指定了c和b属性优先排序,所以序列化后为{“c”:“3”,“b”:“2”,“a”:“1”,“d”:“4”}

@JsonValue

标注方法,用以替代缺省的方法,由该方法来完成json的字符输出

public class PersonValue {

    public long   personId = 0;
    public String name = null;

    @JsonValue
    public String toJson(){
        return this.personId + "," + this.name;
    }

}

输出"0,null"

@JsonFormat

格式化

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")  
public Timestamp getCreate_time() {  
  
        return create_time;  
  
}

@JsonSerialize

@JsonDeserialize相反

@JsonView

@JsonView注解用来过滤序列化对象的字段属性,简单来说就是定义一个标签,根据controller的JsonView属性,将实体类中不同标签的属性进行分类显示。

例:

首先定义一个view类,有两个接口Summary 和SummaryWithDetail :

public class View {
   public interface Summary {}
   public interface SummaryWithDetail extends Summary{}
}

然后定义一个实体类User,选择属性分别加上注解@JsonView(View.Summary.class) 或@JsonView(View.SummaryWithDetail .class)

public class User { 

  @JsonView(View.Summary.class) 
  private Long id; 
  @JsonView(View.Summary.class) 
  private String firstname; 
  @JsonView(View.Summary.class) 
  private String lastname; 

  @JsonView(View.SummaryWithDetail .class) 
  private String email; 
  @JsonView(View.SummaryWithDetail .class) 
  private String address; 

  private String postalCode; 
  private String city; 
  private String country;

  ...
}

定义Controller类,加上@JsonView注解:

@RestController
public class UserRestController{
  @Autowired 
  private UserService userService;

  @RequestMapping("/user")
  @JsonView(View.Summary.class) 
  public List<User> getUsers(){
    return userService.listUsers();
  }

  @RequestMapping("/userWithDetail")
  @JsonView(View.SummaryWithDetail.class) 
  public List<User> getUsersWithDetail(){
    return userService.listUsers();
  }
}

访问/user时,使用的注解是@JsonView(View.Summary.class),所以仅显示注解为@JsonView(View.Summary.class)的属性,结果为:

[ 
{ “id” : 1, “firstname” : “Brian”, “lastname” : “Clozel” }, 
{ “id” : 2, “firstname” : “Stéphane”, “lastname” : “Nicoll” }, 
{ “id” : 3, “firstname” : “Rossen”, “lastname” : “Stoyanchev” } 
]

访问/userWithDetail时,使用的注解是@JsonView(View.SummaryWithDetail.class),结果显示注解为@JsonView(View.SummaryWithDetail.class)的属性,同时由于SummaryWithDetail继承于Summary,结果也包含注解为@JsonView(View.Summary.class)的属性,结果为:

[ 
{ 
“id” : 1, 
“firstname” : “Brian”, 
“lastname” : “Clozel”, 
“email”: “brian@163.com”, 
“address”: “beijing China” 
}, 
{ 
“id” : 2, 
“firstname” : “Stéphane”, 
“lastname” : “Nicoll”, 
“email”: “nicoll@163.com”, 
“address”: “beijing China” 
}, 
{ 
“id” : 3, 
“firstname” : “Rossen”, 
“lastname” : “Stoyanchev” , 
“email”: “stoyanchev@163.com”, 
“address”: “beijing China” 
} 
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值