java中使用fastjson、jackson、json-lib解析JSON-------------------妈妈再也不用担心JSON解析
1、fastjson
引入包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.16</version>
</dependency>
JSON字符串转JSONObject/JSONArray
JSONObject jsonObject = JSONObject.parseObject(jsonString);
得到子节点
jsonObject .getString();
jsonObject .getArray();
jsonObject .getDate();
.....
转为javaBean
JSONObject.toJavaObject(jsonObject,JavaBean.class);
JSON字符串直接转JavaBean
JSONObject.parseObject(jsonString,javaBean.class);
JavaBean转JSON字符串
String jsonString = JSONObject.toJSONString(javaBean)
2、jackson
引入的包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.0</version>
</dependency>
JSON字符串装javaBean
objectMapper = new ObjectMapper();
JavaBean javaBean= objectMapper.readValue(jsonString, JavaBean.class);
javaBean转JSON字符串
objectMapper = new ObjectMapper();
//writeObject可以转换java对象,eg:JavaBean/Map/List/Array等
String jsonString = objectMapper.writeValueAsString(bean);
控制台打印:
jsonGenerator.writeObject(bean);
//writeValue具有和writeObject相同的功能
objectMapper.writeValue(System.out, bean);
获取子节点
ObjectMapper mapper = new ObjectMapper();
// 读取json,将整个json作为根节点
JsonNode node = mapper.readTree(jsonString);
node.path();
node.get();
1. //如果属性没有值,那么Json是会处理的,int类型为0,String类型为null,数组为[],设置这个特性可以忽略空值属性
2. mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
3. //让Json可以缩进,可读性更好,一般用在测试和开发阶段。
4. mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
5. //让map的key按自然顺序排列
6. mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
7. //日期输出格式
8. SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
9. mapper.setDateFormat(outputFormat);
创建节点,生成JSON字符串
1. //创建一个提供所有节点的JsonNodeFactory,false表示不创建DecimalNode
2. JsonNodeFactory factory = new JsonNodeFactory(false);
3.
4. // 创建JsonFactory,使用Streaming API的方式输出到控制台
5. JsonFactory jsonFactory = new JsonFactory();
6. JsonGenerator generator = jsonFactory.createGenerator(System.out);
7. ObjectMapper mapper = new ObjectMapper();
8.
9. //创建节点和数据,一个ObjectNode代表一个节点对象
10. ObjectNode node1 = factory.objectNode();
11. ObjectNode node2 = factory.objectNode();
12. node1.put("A", "a");
13. node1.put("B", "b");
14. node2.set("C", node1);
15.
16. // 根节点
17. ObjectNode root = factory.objectNode();
18. root.put("root", "root");
19. root.set("children", node2);
20. mapper.writeTree(generator, root);
21. //输出{"root":"root","children":{"C":{"A":"a","B":"b"}}}
其他数组、list、map参考
http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html
http://blog.youkuaiyun.com/gjb724332682/article/details/51586701
3、json-lib
使用的包
<!--json-lib-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.6</version>
</dependency>
JSON字符串转JSONObject/JSONArray
JSONObject jsonObject = JSONObject.fromObject(jsonString/javaBean);
得到子节点
jsonObject.getString("success")
转为javaBean
JSONObject.toBean(jsonObject,JavaBean.class);
javaBean转JSON字符串
String jsonString=jsonObject.toString();
list map参照
http://www.cnblogs.com/teach/p/5791029.html
概述
Jackson框架是基于Java平台的一套数据处理工具,被称为“最好的Java Json解析器”。
Jackson框架包含了3个核心库:streaming,databind,annotations.Jackson还包含了其它数据处理类库,此外不作说明。
Jackson版本: 1.x (目前版本从1.1~1.9)与2.x。1.x与2.x从包的命名上可以看出来,1.x的类库中,包命名以:org.codehaus.jackson.xxx开头,而2.x类库中包命令:com.fastxml.jackson.xxx开头
Jackson Home Page:https://github.com/FasterXML/jackson
Jackson Wiki:http://wiki.fasterxml.com/JacksonHome
Jackson doc: https://github.com/FasterXML/jackson-docs
Jackson Download Page:http://wiki.fasterxml.com/JacksonDownload
准备工作
本文所有程序都基于JDK1.7,依赖jackon的三个核心类库:
jackson-core-2.5.3.jar
jackson-annotations-2.5.3.jar
jackson-databind-2.5.3.jar
Jackson处理Json
Jackson提供了三种可选的Json处理方法:流式API(Streaming API) 、树模型(Tree Model)、数据绑定(Data Binding)。从使用角度来看,比较一下这三种处理Json的方式的特性:
Streaming API:是效率最高的处理方式(开销低、读写速度快,但程序编写复杂度高)Tree Model:是最灵活的处理方式
Data Binding:是最常用的处理方式
下面我们通过例子程序分别使用DataBinding,TreeModel,Streaming的方式来创建和解析Json字符串
1.DataBinding处理Json
2.Tree Model处理Json
(1)tree model生成json:
- package com.jackson.json.treemodel;
- import java.io.File;
- import java.io.FileWriter;
- import com.fasterxml.jackson.core.JsonFactory;
- import com.fasterxml.jackson.core.JsonGenerator;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.SerializationFeature;
- import com.fasterxml.jackson.databind.node.ArrayNode;
- import com.fasterxml.jackson.databind.node.JsonNodeFactory;
- import com.fasterxml.jackson.databind.node.ObjectNode;
- public class SerializationExampleTreeModel {
- public static void main(String[] args) throws Exception {
- //创建一个节点工厂,为我们提供所有节点
- JsonNodeFactory factory = new JsonNodeFactory(false);
- //创建一个json factory来写tree modle为json
- JsonFactory jsonFactory = new JsonFactory();
- //创建一个json生成器
- JsonGenerator generator = jsonFactory.createGenerator(new FileWriter(new File("country2.json")));
- //注意,默认情况下对象映射器不会指定根节点,下面设根节点为country
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode country = factory.objectNode();
- country.put("country_id", "China");
- country.put("birthDate", "1949-10-01");
- //在Java中,List和Array转化为json后对应的格式符号都是"obj:[]"
- ArrayNode nation = factory.arrayNode();
- nation.add("Han").add("Meng").add("Hui").add("WeiWuEr").add("Zang");
- country.set("nation", nation);
- ArrayNode lakes = factory.arrayNode();
- lakes.add("QingHai Lake").add("Poyang Lake").add("Dongting Lake").add("Taihu Lake");
- country.set("lakes", lakes);
- ArrayNode provinces = factory.arrayNode();
- ObjectNode province = factory.objectNode();
- ObjectNode province2 = factory.objectNode();
- province.put("name","Shanxi");
- province.put("population", 37751200);
- province2.put("name","ZheJiang");
- province2.put("population", 55080000);
- provinces.add(province).add(province2);
- country.set("provinces", provinces);
- ObjectNode traffic = factory.objectNode();
- traffic.put("HighWay(KM)", 4240000);
- traffic.put("Train(KM)", 112000);
- country.set("traffic", traffic);
- mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
- mapper.writeTree(generator, country);
- }
- }
程序运行生成country2.json,内容如下:
- {"country_id":"China","birthDate":"1949-10-01","nation":["Han","Meng","Hui","WeiWuEr","Zang"],"lakes":["QingHai Lake","Poyang Lake","Dongting Lake","Taihu Lake"],"provinces":[{"name":"Shanxi","population":37751200},{"name":"ZheJiang","population":55080000}],"traffic":{"HighWay(KM)":4240000,"Train(KM)":112000}}
(2) json字符串反序列化为tree mode
DeserializationExampleTreeModel1.java,请注意观察程序中不同的JsonNode的类型变化
- package com.jackson.json.treemodel;
- import java.io.File;
- import java.util.Iterator;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- public class DeserializationExampleTreeModel1 {
- public static void main(String[] args) throws Exception {
- ObjectMapper mapper = new ObjectMapper();
- // Jackson提供一个树节点被称为"JsonNode",ObjectMapper提供方法来读json作为树的JsonNode根节点
- JsonNode node = mapper.readTree(new File("country2.json"));
- // 看看根节点的类型
- System.out.println("node JsonNodeType:"+node.getNodeType());
- // 是不是一个容器
- System.out.println("node is container Node ? "+node.isContainerNode());
- // 得到所有node节点的子节点名称
- System.out.println("---------得到所有node节点的子节点名称-------------------------");
- Iterator<String> fieldNames = node.fieldNames();
- while (fieldNames.hasNext()) {
- String fieldName = fieldNames.next();
- System.out.print(fieldName+" ");
- }
- System.out.println("\n-----------------------------------------------------");
- // as.Text的作用是有值返回值,无值返回空字符串
- JsonNode country_id = node.get("country_id");
- System.out.println("country_id:"+country_id.asText() + " JsonNodeType:"+country_id.getNodeType());
- JsonNode birthDate = node.get("birthDate");
- System.out.println("birthDate:"+birthDate.asText()+" JsonNodeType:"+birthDate.getNodeType());
- JsonNode nation = node.get("nation");
- System.out.println("nation:"+ nation+ " JsonNodeType:"+nation.getNodeType());
- JsonNode lakes = node.get("lakes");
- System.out.println("lakes:"+lakes+" JsonNodeType:"+lakes.getNodeType());
- JsonNode provinces = node.get("provinces");
- System.out.println("provinces JsonNodeType:"+provinces.getNodeType());
- boolean flag = true;
- for (JsonNode provinceElements : provinces) {
- //为了避免provinceElements多次打印,用flag控制打印,能体现provinceElements的JsonNodeType就可以了
- if(flag){
- System.out.println("provinceElements JsonNodeType:"+provinceElements.getNodeType());
- System.out.println("provinceElements is container node? "+provinceElements.isContainerNode());
- flag = false;
- }
- Iterator<String> provinceElementFields = provinceElements.fieldNames();
- while (provinceElementFields.hasNext()) {
- String fieldName = (String) provinceElementFields.next();
- String province;
- if ("population".equals(fieldName)) {
- province = fieldName + ":" + provinceElements.get(fieldName).asInt();
- }else{
- province = fieldName + ":" + provinceElements.get(fieldName).asText();
- }
- System.out.println(province);
- }
- }
- }
- }
程序运行后打印结果如下:
- node JsonNodeType:OBJECT
- node is container Node ? true
- ---------得到所有node节点的子节点名称-------------------------
- country_id birthDate nation lakes provinces traffic
- -----------------------------------------------------
- country_id:China JsonNodeType:STRING
- birthDate:1949-10-01 JsonNodeType:STRING
- nation:["Han","Meng","Hui","WeiWuEr","Zang"] JsonNodeType:ARRAY
- lakes:["QingHai Lake","Poyang Lake","Dongting Lake","Taihu Lake"] JsonNodeType:ARRAY
- provinces JsonNodeType:ARRAY
- provinceElements JsonNodeType:OBJECT
- provinceElements is container node? true
- name:Shanxi
- population:37751200
- name:ZheJiang
- population:55080000
在来看一下DeserializationExampleTreeModel2.java,本例中使用JsonNode.path的方法,path方法类似于DeserializationExampleTreeModel1.java中使用的get方法,
但当node不存在时,get方法返回null,而path返回MISSING类型的JsonNode
- package com.jackson.json.treemodel;
- import java.io.File;
- import java.io.IOException;
- import java.util.Iterator;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- public class DeserializationExampleTreeModle2 {
- public static void main(String[] args) throws JsonProcessingException, IOException{
- ObjectMapper mapper = new ObjectMapper();
- JsonNode node = mapper.readTree(new File("country2.json"));
- //path方法获取JsonNode时,当对象不存在时,返回MISSING类型的JsonNode
- JsonNode missingNode = node.path("test");
- if(missingNode.isMissingNode()){
- System.out.println("JsonNodeType : " + missingNode.getNodeType());
- }
- System.out.println("country_id:"+node.path("country_id").asText());
- JsonNode provinces = node.path("provinces");
- for (JsonNode provinceElements : provinces) {
- Iterator<String> provincesFields = provinceElements.fieldNames();
- while (provincesFields.hasNext()) {
- String fieldName = (String) provincesFields.next();
- String province;
- if("name".equals(fieldName)){
- province = fieldName +":"+ provinceElements.path(fieldName).asText();
- }else{
- province = fieldName +":"+ provinceElements.path(fieldName).asInt();
- }
- System.out.println(province);
- }
- }
- }
- }
- JsonNodeType : MISSING
- country_id:China
- name:Shanxi
- population:37751200
- name:ZheJiang
- population:55080000
3.Stream处理Json
现在adgcountry3.json,我们用Streaming API的方式来解析上面的Json,并查找json中population的值。
总结
概述
jackson解析json例子
准备工作
基于JDK1.7,依赖Jackson框架类库:
jackson-core-2.5.3.jar
jackson-databind-2.5.3.jar
Example
下面的例子是基于Jackson 2.x版本的树模型的Json解析。
要解析的Json字符串:
- String data = {
- "type":2,"range":1,"start":1368417600,"end":1368547140,"cityName":"天津",
- "companyIds":["12000001"],
- "companyNames":["天津"],
- "12000001":{
- "data":[47947,48328,48573,48520],
- "timestamps":[1368417600,1368417900,1368418200,1368418500]
- }
- }
示例代码:
- package com.cennavi.dqe.test;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.TimeZone;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- public class ParseJsonTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- String data = "{\"type\":2,\"range\":1,\"start\":1368417600,\"end\":1368547140,"
- + "\"cityName\":\"天津\",\"companyIds\":[\"12000001\"],\"companyNames\":[\"天津\"],"
- + "\"12000001\":{\"data\":[47947,48328,48573,48520],"
- + "\"timestamps\":[1368417600,1368417900,1368418200,1368418500]}}";
- String data2 = parseJson(data);
- System.out.println(data2);
- }
- public static String parseJson(String data) {
- // 用来展现解析Json得到的值
- StringBuffer buf = new StringBuffer();
- try {
- ObjectMapper mapper = new ObjectMapper();
- JsonNode rootNode = mapper.readTree(data); // 读取Json
- // rootNode.path("xx")返回的还是一个JsonNode对象,调用该JsonNode的相应方法,得到键对应的值
- int type = rootNode.path("type").asInt();
- int range = rootNode.path("range").asInt();
- long start = rootNode.path("start").asLong();
- long end = rootNode.path("end").asLong();
- String cityName = rootNode.path("cityName").asText();
- // 转换时间格式
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
- sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
- String str = "类型(type):" + type + "\r\n" + "范围(range):" + range
- + "\r\n" + "开始时间(start):"
- + sdf.format(new Date(start * 1000)) + "\r\n"
- + "结束时间(end):" + sdf.format(new Date(end * 1000)) + "\r\n"
- + "城市名称(cityName):" + cityName;
- buf.append(str);
- // 得到companyIds的JsonNode对象
- JsonNode companyIds = rootNode.path("companyIds");
- JsonNode companyNames = rootNode.path("companyNames");
- // 遍历companyIds中的内容
- for (int i = 0; i < companyIds.size(); i++) {
- String companyId = companyIds.get(i).asText();
- // 本例解析的Json字符串中companyIds与companyNames的长度是相同的,所有直接遍历companyNames
- String companyName = companyNames.get(i).asText();
- // companyId的值:12000001,对应Json串中的
- // "12000001":{"data":[...],"timestamps":[....]}
- JsonNode infoNode = rootNode.path(companyId);
- // 得到"12000001":{"data":[...],"timestamps":[....]}中的data和timestamps的JsonNode对象
- JsonNode dataNode = infoNode.path("data");
- JsonNode timestampsNode = infoNode.path("timestamps");
- // 遍历data和timestamps 本例中data.size与timestamps.size是相等的
- buf.append("\r\n{\r\n 公司ID(companyId):" + companyId
- + "\r\n 公司名称(companyName):" + companyName + "\r\n"
- + " data:");
- for (int j = 0; j < dataNode.size(); j++) {
- long dataValue = dataNode.get(j).asLong();
- buf.append(dataValue + ",");
- }
- buf.append("\r\n time:");
- for (int k = 0; k < timestampsNode.size(); k++) {
- long timeValue = timestampsNode.get(k).asLong();
- buf.append(sdf.format(new Date(timeValue * 1000)) + ",");
- }
- buf.append("\r\n}\r\n");
- }
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- // TODO 自动生成的 catch 块
- e.printStackTrace();
- }
- return buf.toString();
- }
- }
测试结果:
- 类型(type):2
- 范围(range):1
- 开始时间(start):201305131200
- 结束时间(end):201305142359
- 城市名称(cityName):天津
- {
- 公司ID(companyId):12000001
- 公司名称(companyName):天津
- data:47947,48328,48573,48520,
- time:201305131200,201305131205,201305131210,201305131215
- }
概述
使用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"
- } ]
- }
- 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字段的名称为HQ
- private String headquarters;
- private Department[] departments;
- @JsonIgnore //在序列化与反序列化时,忽略birthDate属性
- private Date birthDate;
- public Date getBirthDate() {
- return birthDate;
- }
- @JsonCreator
- public 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;
- }
- @JsonAnySetter
- public 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,所以此处得到的值应该为null
- Department[] 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_number
- System.out.print("product:"+department.get("product")+"\t");
- System.out.println("projectManager:"+department.get("employee_number"));
- }
- }
- }
程序运行控制台打印结果如下:
- company_name:Oracle headquarters:California birthDate:null
- department_name:development employee_number:jack product:oracle_db projectManager:5000
- department_name:test employee_number:rose product:oracle_test projectManager: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;
- }
- @Override
- public String toString() {
- return "Zoo [name=" + name + ", city=" + city + ", animals=" + animals
- + "]";
- }
- }
- 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;
- }
- 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";
- }
- @Override
- public String toString() {
- return "Lion [name=" + name + ", getName()=" + getName()
- + ", getType()=" + getType() + "]";
- }
- }
- 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";
- }
- @Override
- public 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);
- }
- }
- {
- "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);
- }
- }
- [ {
- "@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之间的相互转化。