Jackson学习笔记(三)
来源:互联网 发布:淘宝店铺介绍怎么写好 编辑:程序博客网 时间:2024/05/10 10:53
概述
使用jackson annotations简化和增强的json解析与生成。
Jackson-2.x通用annotations列表:https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
Jackson-1.x通用annotations列表:http://wiki.fasterxml.com/JacksonAnnotations
准备工作
基于JDK1.7,依赖Jackson框架核心类库:
jackson-core-2.5.3.jar
jackson-annotations-2.5.3.jar
jackson-databind-2.5.3.jar
Jackson - Annotations
想要了解更多内容,请查看annotations列表。下面只列出一些常用的Json注解。
@JsonProperty
它关联json字段到java属性。可以标记属性,也可以用来标记属性的getter/setter方法。当标记属性时,可以对属性字段重命名。当标记方法时,可以把json字段关联到java属性的getter或setter方法。
@JsonCreator
json反序列化为java对象时,该注解用于定义构造函数。当从json创建java时,@JsonCreator注解的构造函数被会调用,如果没有@JsonCreator注解,则默认调用java类的无参构造函数,此时,如果java类中只有有参构造函数,而无默认的无参构造函数,在反序列化时会抛出这样的异常:com.fasterxml.jackson.databind.JsonMappingException,所以,当我们不使用@JsonCreator指定反序列化的构造函数,而又在java类中重载了构造函数时,一定要记得编写类的无参构造函数。
@JsonAnyGetter和@JsonAnySetter
用于标记类方法,设置和读取json字段作为键值对存储到map中,这两个注解标记的方法不会处理任何java类中已经定义过的属性变量,只对java中未定义的json字段作处理。
@JsonIgnoreProperties和@JsonIgnore:
用于标记属性,在json与java之间相互转化时,将忽略被此注解标记的属性。@JsonIgnoreProperties是类级别注解,可以忽略多个属性,@JsonIgnore用来标注单个属性。
@JsonTypeInfo和@JsonSubTypes
用于维持java类的子类信息,将子类对象类型信息嵌入到json中,以便反序列化创建具体的对象。
Example
下面通过例子来演示注解的使用
example.1
读取company.json,反序列化json,创建java对象,并遍历信息
company.json
{ "name" : "Oracle", "HQ" : "California", "birthDate" : "1977-01-01", "departments" : [ { "name" : "development", "employee_number" : 5000, "projectManager" : "jack", "product" : "oracle_db" }, { "name" : "test", "employee_number" : 500, "projectManager" : "rose", "product" : "oracle_test" } ]}Company.java
package com.jackson.json.annotation;import java.util.Date;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonIgnore;import com.fasterxml.jackson.annotation.JsonProperty;public class Company {private String name;@JsonProperty("HQ") //java属性headquarters序列化到json字段的名称为HQprivate String headquarters;private Department[] departments;@JsonIgnore //在序列化与反序列化时,忽略birthDate属性private Date birthDate;public Date getBirthDate() {return birthDate;}@JsonCreatorpublic Company(@JsonProperty("name") String name) {this.name = name;}public String getName() {return name;}public String getHeadquarters() {return headquarters;}public Department[] getDepartments() {return departments;}public void setDepartments(Department[] departments) {this.departments = departments;}}
Department.java
package com.jackson.json.annotation;import java.util.HashMap;import java.util.Map;import com.fasterxml.jackson.annotation.JsonAnyGetter;import com.fasterxml.jackson.annotation.JsonAnySetter;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;public class Department {private String name;private String pm;private Map<String, Object> otherProperties = new HashMap<String, Object>(); //otherProperties用来存放Department中未定义的json字段@JsonCreator //指定json反序列化创建Department对象时调用此构造函数public Department(@JsonProperty("name") String name){this.name = name;}@JsonProperty("projectManager") //将company.json中projectManager字段关联到getPm方法public String getPm() {return pm;}public String getName() {return name;}public Object get(String key) {return otherProperties.get(key);}@JsonAnyGetter //得到所有Department中未定义的json字段的public Map<String, Object> any() {return otherProperties;}@JsonAnySetterpublic void set(String key, Object value) {otherProperties.put(key, value);}}
DeserializationExample.java
package com.jackson.json.annotation;import java.io.File;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;public class DeserializationExample {public static void main(String[] args) throws Exception {ObjectMapper mapper = new ObjectMapper();mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //禁止未知属性打断反序列化Company company = mapper.readValue(new File("company_back.json"), Company.class);System.out.print("company_name:"+company.getName()+"\t");System.out.print("headquarters:"+company.getHeadquarters()+"\t");System.out.println("birthDate:"+company.getBirthDate()); //birthDate被标记为@JsonIgnore,所以此处得到的值应该为nullDepartment[] departments = company.getDepartments();for (Department department : departments) {System.out.print("department_name:" + department.getName()+"\t");System.out.print("employee_number:" + department.getPm()+"\t");//Department中未定义的字段product,employee_numberSystem.out.print("product:"+department.get("product")+"\t"); System.out.println("projectManager:"+department.get("employee_number"));}}}
程序运行控制台打印结果如下:
company_name:Oracleheadquarters:CaliforniabirthDate:nulldepartment_name:developmentemployee_number:jackproduct:oracle_dbprojectManager:5000department_name:testemployee_number:roseproduct:oracle_testprojectManager:500
example.2
下面例子演示,当java对象中包含List<Object>属性时,如何序列化与反序列化。
当java对象中含List<Object>时,如果Object一个抽象类或接口,这里就会出现java多态的现象,比如,List<Animal>,Animal是个抽象类,并且有多个子类时,由于List中保存的Animal没有明确指向具体的子类或实现类,json反序列化java对象时就会抛出提示:Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException:Can not construct instance of Animal, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
@JsonTypeInfo与@JsonSubTypes就是解决此类问题,通过注解,可以在序列化时,保存具体的类型信息到json中,当json反序列到java对象时,就可以根据具体类型信息创建正确的java对象。
Zoo.java
package com.jackson.json.databinding.list;import java.util.List;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;public class Zoo {public String name;public String city;public List<Animal> animals;@JsonCreator public Zoo(@JsonProperty("name") String name, @JsonProperty("city") String city) { this.name = name; this.city = city; }public void setAnimals(List<Animal> animals) {this.animals = animals;}@Overridepublic String toString() {return "Zoo [name=" + name + ", city=" + city + ", animals=" + animals+ "]";}}Animal.java
package com.jackson.json.databinding.list;import com.fasterxml.jackson.annotation.JsonSubTypes;import com.fasterxml.jackson.annotation.JsonSubTypes.Type;import com.fasterxml.jackson.annotation.JsonTypeInfo;import com.fasterxml.jackson.annotation.JsonTypeInfo.As;import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;@JsonTypeInfo(use=Id.CLASS,include=As.PROPERTY,property="@class")@JsonSubTypes({@Type(value=Lion.class,name="lion"),@Type(value=Elephant.class,name="elephant")})public abstract class Animal {String name;String type;}Lion.java
package com.jackson.json.databinding.list;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;public class Lion extends Animal {private String name;@JsonCreator public Lion(@JsonProperty("name") String name) { this.name = name; }public String getName() {return name;}public String getType() {return "carnivorous";}@Overridepublic String toString() {return "Lion [name=" + name + ", getName()=" + getName()+ ", getType()=" + getType() + "]";}}Elephant.java
package com.jackson.json.databinding.list;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;public class Elephant extends Animal {private String name;@JsonCreator public Elephant(@JsonProperty("name") String name) { this.name = name; }public String getName() {return name;}public String getType() {return "herbivorous";}@Overridepublic String toString() {return "Elephant [getName()=" + getName() + ", getType()=" + getType()+ "]";}}
SerializeExmaple.java
package com.jackson.json.databinding.list;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;public class SerializeExample {public static void main(String[] args) throws Exception {Zoo zoo = new Zoo("SH Wild Park", "ShangHai");Lion lion = new Lion("Samba");Elephant elephant = new Elephant("Manny");List<Animal> animals = new ArrayList<Animal>();animals.add(lion);animals.add(elephant);zoo.setAnimals(animals);ObjectMapper mapper = new ObjectMapper();mapper.configure(SerializationFeature.INDENT_OUTPUT, true);mapper.writeValue(new File("zoo.json"), zoo);}}生成zoo.json内容如下:
{ "name" : "SH Wild Park", "city" : "ShangHai", "animals" : [ { "@class" : "com.jackson.json.databinding.list.Lion", "name" : "Samba", "type" : "carnivorous" }, { "@class" : "com.jackson.json.databinding.list.Elephant", "name" : "Manny", "type" : "herbivorous" } ]}
反序列化,DeserializeExmaple.java
package com.jackson.json.databinding.list;import java.io.File;import com.fasterxml.jackson.databind.ObjectMapper;public class DeserializeExample {public static void main(String[] args) throws Exception {ObjectMapper mapper = new ObjectMapper();Zoo zoo = mapper.readValue(new File("zoo.json"), Zoo.class);System.out.println(zoo);}}
这里对反序列化后的Zoo对象不作详细遍历了,只打印toString看一下,结果如下,正确创建了Lion和Elephant对象
Zoo [name=SH Wild Park, city=ShangHai, animals=[Lion [name=Samba, getName()=Samba, getType()=carnivorous], Elephant [getName()=Manny, getType()=herbivorous]]]
我们还可以用另一个种方法来替代JsonSubTypes注释,现在,我们对Animal.java类稍作修改,隐去@JsonSubTypes注解,保留@JsonInfoType注解.这一次,我们直接序列化List<Animal>
SerializeExample2.java
package com.jackson.json.databinding.list;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;public class SerializeExample {public static void main(String[] args) throws Exception {Zoo zoo = new Zoo("SH Wild Park", "ShangHai");Lion lion = new Lion("Samba");Elephant elephant = new Elephant("Manny");List<Animal> animals = new ArrayList<Animal>();animals.add(lion);animals.add(elephant);zoo.setAnimals(animals);ObjectMapper mapper = new ObjectMapper();mapper.configure(SerializationFeature.INDENT_OUTPUT, true);mapper.writerFor(new TypeReference<List<Animal>>() {}).writeValue(new File("animal.json"), animals);}}生成 animal.json,内容如下:
[ { "@class" : "com.jackson.json.databinding.list.Lion", "name" : "Samba", "type" : "carnivorous"}, { "@class" : "com.jackson.json.databinding.list.Elephant", "name" : "Manny", "type" : "herbivorous"} ]
总结
当采用数据绑定(DataBinding)方式处理json时,适当的使用Jackson Annotations可以帮助我们更好的解决问题,特别体现在序列化List时,解决多态的问题,以保证反序化到java对象时的正确性。@JsonAnyGetter,@JsonAnySetter,@JsonProperty都是很常用的注解,可以帮助我们更简洁的处理java对象与json之间的相互转化。
- Jackson学习笔记(三)
- Jackson学习笔记(三)
- JackSon学习笔记(二)
- Jackson 概要学习笔记
- Jackson Annotation学习笔记
- jackson 学习笔记
- JackSon学习笔记(一)
- Jackson学习笔记
- Jackson学习笔记(二)
- Jackson学习笔记(一)
- JackSon学习笔记(一)
- JackSon学习笔记(二)
- JackSon学习笔记(一)
- JackSon学习笔记(一)
- JackSon学习笔记(二)
- Jackson学习笔记
- JackSon学习笔记(一)
- Jackson学习笔记(1)
- Base64编码
- TCHAR、wchar_t、char及字符串处理函数区别
- Android 线性布局(LinearLayout)性能相关
- NSArray全部API学习。
- sgu263:Towers(线段树)
- Jackson学习笔记(三)
- Android 4.1 systrace使用方法(一)
- PHP和javascript中使用正则表达式匹配中文字符串
- MySQL存储过程详解 mysql 存储过程
- 在SAT写作中名词化的用途
- 0-1背包问题
- OnlineJudge判题平台——后台流程
- 汇编语言基础2
- 黑马程序员+Java基础环境的搭建