Jackson学习笔记(三)<转>

概述

使用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

[html] view plain copy

  1. {
  2. "name" : "Oracle",
  3. "HQ" : "California",
  4. "birthDate" : "1977-01-01",
  5. "departments" : [ {
  6. "name" : "development",
  7. "employee_number" : 5000,
  8. "projectManager" : "jack",
  9. "product" : "oracle_db"
  10. }, {
  11. "name" : "test",
  12. "employee_number" : 500,
  13. "projectManager" : "rose",
  14. "product" : "oracle_test"
  15. } ]
  16. }

Company.java

[java] view plain copy

  1. package com.jackson.json.annotation;
  2. import java.util.Date;
  3. import com.fasterxml.jackson.annotation.JsonCreator;
  4. import com.fasterxml.jackson.annotation.JsonIgnore;
  5. import com.fasterxml.jackson.annotation.JsonProperty;
  6. public class Company {
  7. private String name;
  8. @JsonProperty("HQ")   //java属性headquarters序列化到json字段的名称为HQ
  9. private String headquarters;
  10. private Department[] departments;
  11. @JsonIgnore         //在序列化与反序列化时,忽略birthDate属性
  12. private Date birthDate;
  13. public Date getBirthDate() {
  14. return birthDate;
  15. }
  16. @JsonCreator
  17. public Company(@JsonProperty("name") String name) {
  18. this.name = name;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public String getHeadquarters() {
  24. return headquarters;
  25. }
  26. public Department[] getDepartments() {
  27. return departments;
  28. }
  29. public void setDepartments(Department[] departments) {
  30. this.departments = departments;
  31. }
  32. }

Department.java

[java] view plain copy

  1. package com.jackson.json.annotation;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import com.fasterxml.jackson.annotation.JsonAnyGetter;
  5. import com.fasterxml.jackson.annotation.JsonAnySetter;
  6. import com.fasterxml.jackson.annotation.JsonCreator;
  7. import com.fasterxml.jackson.annotation.JsonProperty;
  8. public class Department {
  9. private String name;
  10. private String pm;
  11. private Map<String, Object> otherProperties = new HashMap<String, Object>(); //otherProperties用来存放Department中未定义的json字段
  12. @JsonCreator   //指定json反序列化创建Department对象时调用此构造函数
  13. public Department(@JsonProperty("name") String name){
  14. this.name = name;
  15. }
  16. @JsonProperty("projectManager")  //将company.json中projectManager字段关联到getPm方法
  17. public String getPm() {
  18. return pm;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public Object get(String key) {
  24. return otherProperties.get(key);
  25. }
  26. @JsonAnyGetter    //得到所有Department中未定义的json字段的
  27. public Map<String, Object> any() {
  28. return otherProperties;
  29. }
  30. @JsonAnySetter
  31. public void set(String key, Object value) {
  32. otherProperties.put(key, value);
  33. }
  34. }

DeserializationExample.java

[java] view plain copy

  1. package com.jackson.json.annotation;
  2. import java.io.File;
  3. import com.fasterxml.jackson.databind.DeserializationFeature;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. public class DeserializationExample {
  6. public static void main(String[] args) throws Exception {
  7. ObjectMapper mapper = new ObjectMapper();
  8. mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //禁止未知属性打断反序列化
  9. Company company = mapper.readValue(new File("company_back.json"), Company.class);
  10. System.out.print("company_name:"+company.getName()+"\t");
  11. System.out.print("headquarters:"+company.getHeadquarters()+"\t");
  12. System.out.println("birthDate:"+company.getBirthDate()); //birthDate被标记为@JsonIgnore,所以此处得到的值应该为null
  13. Department[] departments = company.getDepartments();
  14. for (Department department : departments) {
  15. System.out.print("department_name:" + department.getName()+"\t");
  16. System.out.print("employee_number:" + department.getPm()+"\t");
  17. //Department中未定义的字段product,employee_number
  18. System.out.print("product:"+department.get("product")+"\t");
  19. System.out.println("projectManager:"+department.get("employee_number"));
  20. }
  21. }
  22. }

程序运行控制台打印结果如下:

[html] view plain copy

  1. company_name:Oracle headquarters:California birthDate:null
  2. department_name:development employee_number:jack    product:oracle_db   projectManager:5000
  3. 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

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import java.util.List;
  3. import com.fasterxml.jackson.annotation.JsonCreator;
  4. import com.fasterxml.jackson.annotation.JsonProperty;
  5. public class Zoo {
  6. public String name;
  7. public String city;
  8. public List<Animal> animals;
  9. @JsonCreator
  10. public Zoo(@JsonProperty("name") String name, @JsonProperty("city") String city) {
  11. this.name = name;
  12. this.city = city;
  13. }
  14. public void setAnimals(List<Animal> animals) {
  15. this.animals = animals;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Zoo [name=" + name + ", city=" + city + ", animals=" + animals
  20. + "]";
  21. }
  22. }

Animal.java

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import com.fasterxml.jackson.annotation.JsonSubTypes;
  3. import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
  4. import com.fasterxml.jackson.annotation.JsonTypeInfo;
  5. import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
  6. import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
  7. @JsonTypeInfo(use=Id.CLASS,include=As.PROPERTY,property="@class")
  8. @JsonSubTypes({@Type(value=Lion.class,name="lion"),@Type(value=Elephant.class,name="elephant")})
  9. public abstract class Animal {
  10. String name;
  11. String type;
  12. }

Lion.java

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import com.fasterxml.jackson.annotation.JsonCreator;
  3. import com.fasterxml.jackson.annotation.JsonProperty;
  4. public class Lion extends Animal {
  5. private String name;
  6. @JsonCreator
  7. public Lion(@JsonProperty("name") String name) {
  8. this.name = name;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public String getType() {
  14. return "carnivorous";
  15. }
  16. @Override
  17. public String toString() {
  18. return "Lion [name=" + name + ", getName()=" + getName()
  19. + ", getType()=" + getType() + "]";
  20. }
  21. }

Elephant.java

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import com.fasterxml.jackson.annotation.JsonCreator;
  3. import com.fasterxml.jackson.annotation.JsonProperty;
  4. public class Elephant extends Animal {
  5. private String name;
  6. @JsonCreator
  7. public Elephant(@JsonProperty("name") String name) {
  8. this.name = name;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public String getType() {
  14. return "herbivorous";
  15. }
  16. @Override
  17. public String toString() {
  18. return "Elephant [getName()=" + getName() + ", getType()=" + getType()
  19. + "]";
  20. }
  21. }

SerializeExmaple.java

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. import com.fasterxml.jackson.databind.ObjectMapper;
  7. import com.fasterxml.jackson.databind.SerializationFeature;
  8. public class SerializeExample {
  9. public static void main(String[] args) throws Exception {
  10. Zoo zoo = new Zoo("SH Wild Park", "ShangHai");
  11. Lion lion = new Lion("Samba");
  12. Elephant elephant = new Elephant("Manny");
  13. List<Animal> animals = new ArrayList<Animal>();
  14. animals.add(lion);
  15. animals.add(elephant);
  16. zoo.setAnimals(animals);
  17. ObjectMapper mapper = new ObjectMapper();
  18. mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
  19. mapper.writeValue(new File("zoo.json"), zoo);
  20. }
  21. }

生成zoo.json内容如下:

[html] view plain copy

  1. {
  2. "name" : "SH Wild Park",
  3. "city" : "ShangHai",
  4. "animals" : [ {
  5. "@class" : "com.jackson.json.databinding.list.Lion",
  6. "name" : "Samba",
  7. "type" : "carnivorous"
  8. }, {
  9. "@class" : "com.jackson.json.databinding.list.Elephant",
  10. "name" : "Manny",
  11. "type" : "herbivorous"
  12. } ]
  13. }

反序列化,DeserializeExmaple.java

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import java.io.File;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. public class DeserializeExample {
  5. public static void main(String[] args) throws Exception {
  6. ObjectMapper mapper = new ObjectMapper();
  7. Zoo zoo = mapper.readValue(new File("zoo.json"), Zoo.class);
  8. System.out.println(zoo);
  9. }
  10. }

这里对反序列化后的Zoo对象不作详细遍历了,只打印toString看一下,结果如下,正确创建了Lion和Elephant对象

[html] view plain copy

  1. 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

[java] view plain copy

  1. package com.jackson.json.databinding.list;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. import com.fasterxml.jackson.core.type.TypeReference;
  7. import com.fasterxml.jackson.databind.ObjectMapper;
  8. import com.fasterxml.jackson.databind.SerializationFeature;
  9. public class SerializeExample {
  10. public static void main(String[] args) throws Exception {
  11. Zoo zoo = new Zoo("SH Wild Park", "ShangHai");
  12. Lion lion = new Lion("Samba");
  13. Elephant elephant = new Elephant("Manny");
  14. List<Animal> animals = new ArrayList<Animal>();
  15. animals.add(lion);
  16. animals.add(elephant);
  17. zoo.setAnimals(animals);
  18. ObjectMapper mapper = new ObjectMapper();
  19. mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
  20. mapper.writerFor(new TypeReference<List<Animal>>() {
  21. }).writeValue(new File("animal.json"), animals);
  22. }
  23. }

生成 animal.json,内容如下:

[html] view plain copy

  1. [ {
  2. "@class" : "com.jackson.json.databinding.list.Lion",
  3. "name" : "Samba",
  4. "type" : "carnivorous"
  5. }, {
  6. "@class" : "com.jackson.json.databinding.list.Elephant",
  7. "name" : "Manny",
  8. "type" : "herbivorous"
  9. } ]

总结

当采用数据绑定(DataBinding)方式处理json时,适当的使用Jackson Annotations可以帮助我们更好的解决问题,特别体现在序列化List时,解决多态的问题,以保证反序化到java对象时的正确性。@JsonAnyGetter,@JsonAnySetter,@JsonProperty都是很常用的注解,可以帮助我们更简洁的处理java对象与json之间的相互转化。

转自 http://blog.csdn.net/java_huashan/article/details/46428971

时间: 2024-10-05 17:19:49

Jackson学习笔记(三)<转>的相关文章

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T> 今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子 看一它的的实现和源码 下一篇用它们做一个多语言的demo 这两个是事件的订阅和广播,很强大,但用的时候要小心发生不必要的冲突. 先看一下它的实现思想 在Caliburn.Micro里EventAggregator要以单例的形式出现这样可以

OpenCV for Python 学习笔记 三

给源图像增加边界 cv2.copyMakeBorder(src,top, bottom, left, right ,borderType,value) src:源图像 top,bottem,left,right: 分别表示四个方向上边界的长度 borderType: 边界的类型 有以下几种: BORDER_REFLICATE # 直接用边界的颜色填充, aaaaaa | abcdefg | gggg BORDER_REFLECT # 倒映,abcdefg | gfedcbamn | nmabcd

NFC学习笔记——三(在windows操作系统上安装libnfc)

本篇翻译文章: 这篇文章主要是说明如何在windows操作系统上安装.配置和使用libnfc. 一.基本信息 1.操作系统: Windows Vista Home Premium SP 2 2.硬件信息: System: Dell Inspiron 1720 Processor: Intel Core 2 Duo CPU T9300 @ 2.5GHz 2.5GHz System type: 32-bit Operating System 3.所需软件: 在windows操作系统上安装软件需要下列

swift学习笔记(三)关于拷贝和引用

在swift提供的基本数据类型中,包括Int ,Float,Double,String,Enumeration,Structure,Dictionary都属于值拷贝类型. 闭包和函数同属引用类型 捕获则为拷贝.捕获即定义这些常量和变量的原作用域已不存在,闭包仍然可以在闭包函数体内引用和修改这些值 class属于引用类型. Array的情况稍微复杂一些,下面主要对集合类型进行分析: 一.关于Dictionary:无论何时将一个字典实例赋给一个常量,或者传递给一个函数方法时,在赋值或调用发生时,都会

加壳学习笔记(三)-简单的脱壳思路&amp;调试思路

首先一些windows的常用API: GetWindowTextA:以ASCII的形式的输入框 GetWindowTextW:以Unicaode宽字符的输入框 GetDlgItemTextA:以ASCII的形式的输入框 GetDlgItemTextW:以Unicaode宽字符的输入框 这些函数在使用的时候会有些参数提前入栈,如这函数要求的参数是字符串数目.还有大小写啦之类的东西,这些东西是要在调用该函数之前入栈,也就是依次push,就是说一般前面几个push接着一个call,那前面的push可能

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

马哥学习笔记三十二——计算机及操作系统原理

缓存方式: 直接映射 N路关联 缓存策略: write through:通写 write back:回写 进程类别: 交互式进程(IO密集型) 批处理进程(CPU密集型) 实时进程(Real-time) CPU: 时间片长,优先级低IO:时间片短,优先级高 Linux优先级:priority 实时优先级: 1-99,数字越小,优先级越低 静态优先级:100-139,数据越小,优先级越高 实时优先级比静态优先级高 nice值:调整静态优先级   -20,19:100,139   0:120 ps

lucene学习笔记(三)

好几天没更新了.更新一下,方便自己和大家学习. 这是最基本的代码 package index; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document;

python 学习笔记 三 字典

字典 Python的高效的key/value哈希表结构叫做"dict", dict的内容可以写成一系列的key:value对并放入{ }中, 相当于: dict = {key1:value1, key2:value2, ...}, 一个空的字典就是俩个大括号{ }. 下面是从一个空字典创建字典以及一些关键点: 数字, 字符串和元组可以作为字典的key, value可以是任何类型(包括字典). ## Can build up a dict by starting with the the