Jackson入门教程

转载自:http://blog.csdn.net/gjb724332682/article/details/51586701

相关地址


简介

    Jackson是一套Java平台的数据处理工具集,具体可以参考官网的说法:
including the flagship streaming JSON parser / generator library, matching data-binding library (POJOs to and from JSON) and additional data format modules to process data encoded in Avro, BSON, CBOR, CSV, Smile, Protobuf, XML or YAML; and even the large set of data format modules to support data types of widely used data types such as Joda, Guava and many, many more.
    Jackson有两个主要分支,1.x处于维护状态,只会发布bug修复版本。2.x还在积极地开发当中。这两个版本的Java包名和Maven artifact不一样,所以它们不互相兼容,但是可以和平共存,也就是项目可以同时依赖1.x和2.x而不会发生冲突,本文只会简单介绍2.x版本的用法。

Jackson主要模块

核心模块

    核心模块是扩展模块构建的基础,到2.7版本为止,共有3个核心模块:
Streaming : jackson-core jar,定义了底层的streaming API和实现了Json特性。
Annotations: jackson-annotations jar,包含了标准的Jackson注解。本文暂不介绍。
Databind : jackson-databind jar,实现了数据绑定和对象序列化,它依赖于streaming和annotations的包。

第三方数据类型模块

    这些扩展是插件式的Jackson模块,用ObjectMapper.registerModule()注册,并且通过添加serializers和deserializers以便Databind包(ObjectMapper / ObjectReader / ObjectWriter)可以读写这些类型,来增加对各种常用的Java库的数据类型的支持。参考https://github.com/FasterXML/jacksonThird-party datatype modules。

数据格式模块

    Jackson也有处理程序对JAX-RS标准实现者例如Jersey, RESTeasy, CXF等提供了数据格式支持。处理程序实现了MessageBodyReader和MessageBodyWriter,目前支持的数据格式包括JSON, Smile, XML, YAML和CBOR。
    数据格式提供了除了Json之外的数据格式支持,它们绝大部分仅仅实现了streaming API abstractions,以便数据绑定组件可以按照原来的方式使用。另一些(几乎不需要)提供了databind标准功能来处理例如schemas。参考https://github.com/FasterXML/jacksonData format modules

准备工作

    Jackson包含了一个核心的jar包和其他两个依赖于核心jar包的jar包,三者的依赖关系是从上到下的,如下:
Jackson Core
Jackson Annotations
Jackson Databind

       可以从https://github.com/FasterXML下载Jackson的jar包,或者采用maven来管理。如果是maven的方式,需要加入如下的依赖:
[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <dependency>  
  2.   <groupId>com.fasterxml.jackson.core</groupId>  
  3.   <artifactId>jackson-core</artifactId>  
  4.   <version>2.7.4</version>  
  5. </dependency>  
  6.   
  7. <dependency>  
  8.   <groupId>com.fasterxml.jackson.core</groupId>  
  9.   <artifactId>jackson-annotations</artifactId>  
  10.   <version>2.7.4</version>  
  11. </dependency>  
  12.   
  13. <dependency>  
  14.   <groupId>com.fasterxml.jackson.core</groupId>  
  15.   <artifactId>jackson-databind</artifactId>  
  16.   <version>2.7.4</version>  
  17. </dependency>  

处理Json

    本文用JDK7.0的版本。Jackson提供了三种可选的Json处理方法:数据绑定(Data Binding),流式API(Streaming API) 、树模型(Tree Model)。

Data Binding

    我们主要使用ObjectMapper来操作Json,默认情况下会使用BeanSerializer来序列化POJO。如果是解析,那么如下的例子里的TestJson必须要有setters,且setters必须是public修饰的,否则属性的值将会为null。如果是生成,那么必须有getters,且getters必须是public修饰的。如果属性不是private修饰,那么可以不用有getters和setters。这参考访问修饰符。

Json解析     
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public class Demo {  
  2.     public static void main(String[] args) throws Exception {  
  3.         ObjectMapper mapper = new ObjectMapper();  
  4.   
  5. //        当反序列化json时,未知属性会引起的反序列化被打断,这里我们禁用未知属性打断反序列化功能,  
  6. //        因为,例如json里有10个属性,而我们的bean中只定义了2个属性,其它8个属性将被忽略  
  7.         mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);  
  8.   
  9.         //从json映射到java对象,得到country对象后就可以遍历查找,下面遍历部分内容,能说明问题就可以了  
  10.         TestJson testJson = mapper.readValue("{\"a\":\"1\",\"b\":\"2\",\"c\":\"test\",\"d\":\"true\",\"e\":\"e\"}", TestJson.class);  
  11.         System.out.println("a:" + testJson.getA());  
  12.         System.out.println("b:" + testJson.getB());  
  13.         System.out.println("c:" + testJson.getC());  
  14.         System.out.println("d:" + testJson.getD());  
  15.     }  
  16. }  
  17.   
  18. class TestJson {  
  19.     private Integer a;  
  20.     private Integer b;  
  21.     private String c;  
  22.     private Boolean d;  
  23.   
  24.     public Integer getA() {  
  25.         return a;  
  26.     }  
  27.   
  28.     public void setA(Integer a) {  
  29.         this.a = a;  
  30.     }  
  31.   
  32.     public Integer getB() {  
  33.         return b;  
  34.     }  
  35.   
  36.     public void setB(Integer b) {  
  37.         this.b = b;  
  38.     }  
  39.   
  40.     public String getC() {  
  41.         return c;  
  42.     }  
  43.   
  44.     public void setC(String c) {  
  45.         this.c = c;  
  46.     }  
  47.   
  48.     public Boolean getD() {  
  49.         return d;  
  50.     }  
  51.   
  52.     public void setD(Boolean d) {  
  53.         this.d = d;  
  54.     }  
  55. }  
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 输出:  
  2. a:1  
  3. b:2  
  4. c:test  
  5. d:true  

解析的时候如果碰到集合类,那么可以使用TypeReference<T>类。
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static <T> T json2Obj(String jsonStr, TypeReference<T> typeReference, String dateFormat)  
  2.             throws Exception {  
  3.         ObjectMapper objectMapper = getObjectMapper();  
  4.         if (dateFormat != null && !dateFormat.trim().equals("")) {  
  5.             objectMapper.setDateFormat(new SimpleDateFormat(dateFormat));  
  6.         }  
  7.   
  8.         return objectMapper.readValue(jsonStr, typeReference);  
  9.     }  


Json生成
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. import com.fasterxml.jackson.annotation.JsonInclude;  
  2. import com.fasterxml.jackson.databind.ObjectMapper;  
  3. import com.fasterxml.jackson.databind.PropertyNamingStrategy;  
  4. import com.fasterxml.jackson.databind.SerializationFeature;  
  5. import com.fasterxml.jackson.databind.cfg.MapperConfig;  
  6. import com.fasterxml.jackson.databind.introspect.AnnotatedField;  
  7. import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;  
  8.   
  9.   
  10. import java.io.IOException;  
  11. import java.text.ParseException;  
  12. import java.text.SimpleDateFormat;  
  13. import java.util.*;  
  14.   
  15.   
  16. public class SerializationExample {  
  17.     public static void main(String[] args) throws IOException, ParseException {  
  18.         ObjectMapper mapper = new ObjectMapper();  
  19.         Album album = new Album("Kind Of Blue");  
  20.         album.setLinks(new String[]{"link1""link2"});  
  21.         List<String> songs = new ArrayList<String>();  
  22.         songs.add("So What");  
  23.         songs.add("Flamenco Sketches");  
  24.         songs.add("Freddie Freeloader");  
  25.         album.setSongs(songs);  
  26.         Artist artist = new Artist();  
  27.         artist.name = "Miles Davis";  
  28.         SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");  
  29.         artist.birthDate = format.parse("26-05-1926");  
  30.         album.setArtist(artist);  
  31.         album.addMusician("Miles Davis""Trumpet, Band leader");  
  32.         album.addMusician("Julian Adderley""Alto Saxophone");  
  33.         album.addMusician("Paul Chambers""double bass");  
  34.   
  35.   
  36.         //让Json可以缩进,可读性更好,一般用在测试和开发阶段。  
  37.         mapper.configure(SerializationFeature.INDENT_OUTPUT, true);  
  38.         //让map的key按自然顺序排列  
  39.         mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);  
  40.         //日期输出格式  
  41.         SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");  
  42.         mapper.setDateFormat(outputFormat);  
  43.         //默认情况下java类属性名就是输出的json字段名,但是可以采用注解的方式修改。如果你不想让java类和json绑定  
  44.         // 或者无法修改java类,这里采用如下另外一种方式。你需要重写如下两个方法,这个取决属性是public或者getter是public  
  45.         mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {  
  46.             /** 
  47.              * @param config  Configuration in used: either SerializationConfig or DeserializationConfig, depending on whether method is called during serialization or deserialization 
  48.              * @param field Field used to access property 
  49.              * @param defaultName Default name that would be used for property in absence of custom strategy 
  50.              * @return 
  51.              */  
  52.             @Override  
  53.             public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {  
  54.                 if (field.getFullName().equals("Artist#name"))  
  55.                     return "Artist-Name";  
  56.                 return super.nameForField(config, field, defaultName);  
  57.             }  
  58.   
  59.   
  60.             /** 
  61.              * @param config  Configuration in used: either SerializationConfig or DeserializationConfig, depending on whether method is called during serialization or deserialization 
  62.              * @param method  Method used to access property. 
  63.              * @param defaultName Default name that would be used for property in absence of custom strategy 
  64.              * @return 
  65.              */  
  66.             @Override  
  67.             public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {  
  68.                 if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))  
  69.                     return "Album-Title";  
  70.                 return super.nameForGetterMethod(config, method, defaultName);  
  71.             }  
  72.         });  
  73.         //如果属性没有值,那么Json是会处理的,int类型为0,String类型为null,数组为[],设置这个特性可以忽略空值属性  
  74.         mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);  
  75.         mapper.writeValue(System.out, album);  
  76.     }  
  77. }  
  78.   
  79.   
  80. class Album {  
  81.     private String title;  
  82.     private String[] links;  
  83.     private List<String> songs = new ArrayList<String>();  
  84.     private Artist artist;  
  85.     private Map<String, String> musicians = new HashMap<String, String>();  
  86.   
  87.   
  88.     public Album(String title) {  
  89.         this.title = title;  
  90.     }  
  91.   
  92.   
  93.     public String getTitle() {  
  94.         return title;  
  95.     }  
  96.   
  97.   
  98.     public void setLinks(String[] links) {  
  99.         this.links = links;  
  100.     }  
  101.   
  102.   
  103.     public String[] getLinks() {  
  104.         return links;  
  105.     }  
  106.   
  107.   
  108.     public void setSongs(List<String> songs) {  
  109.         this.songs = songs;  
  110.     }  
  111.   
  112.   
  113.     public List<String> getSongs() {  
  114.         return songs;  
  115.     }  
  116.   
  117.   
  118.     public void setArtist(Artist artist) {  
  119.         this.artist = artist;  
  120.     }  
  121.   
  122.   
  123.     public Artist getArtist() {  
  124.         return artist;  
  125.     }  
  126.   
  127.   
  128.     public Map<String, String>  
  129.   
  130.   
  131.     getMusicians() {  
  132.         return Collections.unmodifiableMap(musicians);  
  133.     }  
  134.   
  135.   
  136.     public void addMusician(String key, String value) {  
  137.         musicians.put(key, value);  
  138.     }  
  139. }  
  140.   
  141.   
  142. class Artist {  
  143.     public String name;  
  144.     public Date birthDate;  
  145.     public int age;  
  146.     public String homeTown;  
  147.     public List<String> awardsWon = new ArrayList<String>();  
  148. }  
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 输出:  
  2. {  
  3.   "Album-Title" : "Kind Of Blue",  
  4.   "links" : [ "link1""link2" ],  
  5.   "songs" : [ "So What""Flamenco Sketches""Freddie Freeloader" ],  
  6.   "artist" : {  
  7.     "Artist-Name" : "Miles Davis",  
  8.     "birthDate" : "1926-05-26",  
  9.     "age" : 0  
  10.   },  
  11.   "musicians" : {  
  12.     "Julian Adderley" : "Alto Saxophone",  
  13.     "Miles Davis" : "Trumpet, Band leader",  
  14.     "Paul Chambers" : "double bass"  
  15.   }  
  16. }  

Streaming API

    Jackson提供了一套底层API来解析Json字符串,这个API为每个Json对象提供了符号。例如, '{' 是解析器提供的第一个对象(writeStartObject()),键值对是解析器提供的另一个单独对象(writeString(key,value))。这些API很强大,但是需要大量的代码。大多数情况下,Tree Model和Data Binding可以代替Streaming API。

Json解析
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) throws IOException {  
  2.         // 从JsonFactory获得一个JsonParser实例  
  3.         JsonFactory factory = new JsonFactory();  
  4.         //createParser有很多种重载,具体可以看API  
  5.         JsonParser parser = factory.createParser("{\"title\":\"Free Music Archive - Albums\",\"message\":\"test\",\"errors\":[\"invalid or disabled api_key\"],\"dataset\":[{\"id\":\"1\"},{\"id\":\"2\"}]}");  
  6.   
  7.         // 解析符号直到字符串结尾  
  8.         while (!parser.isClosed()) {  
  9.             // 如果有必要的话,这个方法会沿着流前进直到足以确下一个JsonToken的类型  
  10.             JsonToken token = parser.nextToken();  
  11.             // 如果是最后一个JsonToken,那么就结束了  
  12.             if (token == null)  
  13.                 break;  
  14.             //如果JsonToken是JsonToken.FIELD_NAME类型并且当前的name是dataset  
  15.             if (JsonToken.FIELD_NAME.equals(token) && "dataset".equals(parser.getCurrentName())) {  
  16.                 // 开始解析dateset,第一个JsonToken必须是JsonToken.START_ARRAY"["  
  17.                 token = parser.nextToken();  
  18.                 if (!JsonToken.START_ARRAY.equals(token)) {  
  19.                     break;  
  20.                 }  
  21.                 // 数组的每个元素都是对象,因此下一个JsonToken是JsonToken.START_OBJECT"{"  
  22.                 token = parser.nextToken();  
  23.                 if (!JsonToken.START_OBJECT.equals(token)) {  
  24.                     break;  
  25.                 }  
  26.                 // 输出id字段的值  
  27.                 while (true) {  
  28.                     token = parser.nextToken();  
  29.                     if (token == null)  
  30.                         break;  
  31.                     if (JsonToken.FIELD_NAME.equals(token) && "id".equals(parser.getCurrentName())) {  
  32.                         token = parser.nextToken();  
  33.                         System.out.println(parser.getText());  
  34.                     }  
  35.                 }  
  36.             }  
  37.         }  
  38.     }  

Json生成
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) throws IOException {  
  2.         JsonFactory factory = new JsonFactory();  
  3.         JsonGenerator generator = factory.createGenerator(new BufferedOutputStream(System.out));  
  4.   
  5.         generator.writeStartObject();//{  
  6.         generator.writeFieldName("title");  
  7.         generator.writeString("Free Music Archive - Albums");  
  8.         generator.writeFieldName("dataset");  
  9.         generator.writeStartArray();//[  
  10.         generator.writeStartObject();//{  
  11.         generator.writeStringField("album_title""A.B.A.Y.A.M");  
  12.         generator.writeEndObject();//}  
  13.         generator.writeEndArray();//]  
  14.         generator.writeEndObject();//}  
  15.     //输出{"title":"Free Music Archive - Albums","dataset":[{"album_title":"A.B.A.Y.A.M"}]}  
  16.   
  17.         generator.close();  
  18.     }  

Tree Mode

    如果你不想为你的Json结构写一个class的话,Tree Mode是一个很好的选择。

JSON生成
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) throws IOException {  
  2.         //创建一个提供所有节点的JsonNodeFactory,false表示不创建DecimalNode  
  3.         JsonNodeFactory factory = new JsonNodeFactory(false);  
  4.   
  5.         // 创建JsonFactory,使用Streaming API的方式输出到控制台  
  6.         JsonFactory jsonFactory = new JsonFactory();  
  7.         JsonGenerator generator = jsonFactory.createGenerator(System.out);  
  8.         ObjectMapper mapper = new ObjectMapper();  
  9.   
  10.         //创建节点和数据,一个ObjectNode代表一个节点对象  
  11.         ObjectNode node1 = factory.objectNode();  
  12.         ObjectNode node2 = factory.objectNode();  
  13.         node1.put("A""a");  
  14.         node1.put("B""b");  
  15.         node2.set("C", node1);  
  16.   
  17.         // 根节点  
  18.         ObjectNode root = factory.objectNode();  
  19.         root.put("root""root");  
  20.         root.set("children", node2);  
  21.         mapper.writeTree(generator, root);  
  22.     //输出{"root":"root","children":{"C":{"A":"a","B":"b"}}}  
  23.     }  

Json解析
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) throws Exception {  
  2.         ObjectMapper mapper = new ObjectMapper();  
  3.         // 读取json,将整个json作为根节点  
  4.         JsonNode node = mapper.readTree("{\"root\":\"root\",\"children\":{\"C\":{\"A\":\"a\",\"B\":\"b\"}}}");  
  5.         // 看看根节点的类型  
  6.         System.out.println("node JsonNodeType:" + node.getNodeType());//OBJECT  
  7.         // 是不是一个ContainerNode(array and object nodes)  
  8.         System.out.println("node is containerNode ? " + node.isContainerNode());//true  
  9.         // 得到所有node节点的直接子节点名称  
  10.         Iterator<String> fieldNames = node.fieldNames();  
  11.         while (fieldNames.hasNext()) {  
  12.             String fieldName = fieldNames.next();  
  13.             System.out.println(fieldName + " ");//root children  
  14.         }  
  15.         System.out.println(node.get("root").isContainerNode());//false  
  16.     }  

总结

    这只是基本的用法,其他的如果有用到,再继续添加进来。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值