转载自: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。
准备工作
Jackson包含了一个核心的jar包和其他两个依赖于核心jar包的jar包,三者的依赖关系是从上到下的,如下:
Jackson Core
Jackson Annotations
Jackson Databind
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.7.4</version>
- </dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.7.4</version>
- </dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.7.4</version>
- </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解析
- public class Demo {
- public static void main(String[] args) throws Exception {
- ObjectMapper mapper = new ObjectMapper();
-
-
-
- mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
-
-
- TestJson testJson = mapper.readValue("{\"a\":\"1\",\"b\":\"2\",\"c\":\"test\",\"d\":\"true\",\"e\":\"e\"}", TestJson.class);
- System.out.println("a:" + testJson.getA());
- System.out.println("b:" + testJson.getB());
- System.out.println("c:" + testJson.getC());
- System.out.println("d:" + testJson.getD());
- }
- }
-
- class TestJson {
- private Integer a;
- private Integer b;
- private String c;
- private Boolean d;
-
- public Integer getA() {
- return a;
- }
-
- public void setA(Integer a) {
- this.a = a;
- }
-
- public Integer getB() {
- return b;
- }
-
- public void setB(Integer b) {
- this.b = b;
- }
-
- public String getC() {
- return c;
- }
-
- public void setC(String c) {
- this.c = c;
- }
-
- public Boolean getD() {
- return d;
- }
-
- public void setD(Boolean d) {
- this.d = d;
- }
- }
- 输出:
- a:1
- b:2
- c:test
- d:true
解析的时候如果碰到集合类,那么可以使用TypeReference<T>类。
- public static <T> T json2Obj(String jsonStr, TypeReference<T> typeReference, String dateFormat)
- throws Exception {
- ObjectMapper objectMapper = getObjectMapper();
- if (dateFormat != null && !dateFormat.trim().equals("")) {
- objectMapper.setDateFormat(new SimpleDateFormat(dateFormat));
- }
-
- return objectMapper.readValue(jsonStr, typeReference);
- }
Json生成
- import com.fasterxml.jackson.annotation.JsonInclude;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.PropertyNamingStrategy;
- import com.fasterxml.jackson.databind.SerializationFeature;
- import com.fasterxml.jackson.databind.cfg.MapperConfig;
- import com.fasterxml.jackson.databind.introspect.AnnotatedField;
- import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
-
-
- import java.io.IOException;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.*;
-
-
- public class SerializationExample {
- public static void main(String[] args) throws IOException, ParseException {
- ObjectMapper mapper = new ObjectMapper();
- Album album = new Album("Kind Of Blue");
- album.setLinks(new String[]{"link1", "link2"});
- List<String> songs = new ArrayList<String>();
- songs.add("So What");
- songs.add("Flamenco Sketches");
- songs.add("Freddie Freeloader");
- album.setSongs(songs);
- Artist artist = new Artist();
- artist.name = "Miles Davis";
- SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
- artist.birthDate = format.parse("26-05-1926");
- album.setArtist(artist);
- album.addMusician("Miles Davis", "Trumpet, Band leader");
- album.addMusician("Julian Adderley", "Alto Saxophone");
- album.addMusician("Paul Chambers", "double bass");
-
-
-
- mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
-
- mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
-
- SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
- mapper.setDateFormat(outputFormat);
-
-
- mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
-
-
-
-
-
-
- @Override
- public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
- if (field.getFullName().equals("Artist#name"))
- return "Artist-Name";
- return super.nameForField(config, field, defaultName);
- }
-
-
-
-
-
-
-
-
- @Override
- public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
- if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))
- return "Album-Title";
- return super.nameForGetterMethod(config, method, defaultName);
- }
- });
-
- mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
- mapper.writeValue(System.out, album);
- }
- }
-
-
- class Album {
- private String title;
- private String[] links;
- private List<String> songs = new ArrayList<String>();
- private Artist artist;
- private Map<String, String> musicians = new HashMap<String, String>();
-
-
- public Album(String title) {
- this.title = title;
- }
-
-
- public String getTitle() {
- return title;
- }
-
-
- public void setLinks(String[] links) {
- this.links = links;
- }
-
-
- public String[] getLinks() {
- return links;
- }
-
-
- public void setSongs(List<String> songs) {
- this.songs = songs;
- }
-
-
- public List<String> getSongs() {
- return songs;
- }
-
-
- public void setArtist(Artist artist) {
- this.artist = artist;
- }
-
-
- public Artist getArtist() {
- return artist;
- }
-
-
- public Map<String, String>
-
-
- getMusicians() {
- return Collections.unmodifiableMap(musicians);
- }
-
-
- public void addMusician(String key, String value) {
- musicians.put(key, value);
- }
- }
-
-
- class Artist {
- public String name;
- public Date birthDate;
- public int age;
- public String homeTown;
- public List<String> awardsWon = new ArrayList<String>();
- }
- 输出:
- {
- "Album-Title" : "Kind Of Blue",
- "links" : [ "link1", "link2" ],
- "songs" : [ "So What", "Flamenco Sketches", "Freddie Freeloader" ],
- "artist" : {
- "Artist-Name" : "Miles Davis",
- "birthDate" : "1926-05-26",
- "age" : 0
- },
- "musicians" : {
- "Julian Adderley" : "Alto Saxophone",
- "Miles Davis" : "Trumpet, Band leader",
- "Paul Chambers" : "double bass"
- }
- }
Streaming API
Jackson提供了一套底层API来解析Json字符串,这个API为每个Json对象提供了符号。例如, '{' 是解析器提供的第一个对象(writeStartObject()),键值对是解析器提供的另一个单独对象(writeString(key,value))。这些API很强大,但是需要大量的代码。大多数情况下,Tree Model和Data Binding可以代替Streaming API。
Json解析
- public static void main(String[] args) throws IOException {
-
- JsonFactory factory = new JsonFactory();
-
- JsonParser parser = factory.createParser("{\"title\":\"Free Music Archive - Albums\",\"message\":\"test\",\"errors\":[\"invalid or disabled api_key\"],\"dataset\":[{\"id\":\"1\"},{\"id\":\"2\"}]}");
-
-
- while (!parser.isClosed()) {
-
- JsonToken token = parser.nextToken();
-
- if (token == null)
- break;
-
- if (JsonToken.FIELD_NAME.equals(token) && "dataset".equals(parser.getCurrentName())) {
-
- token = parser.nextToken();
- if (!JsonToken.START_ARRAY.equals(token)) {
- break;
- }
-
- token = parser.nextToken();
- if (!JsonToken.START_OBJECT.equals(token)) {
- break;
- }
-
- while (true) {
- token = parser.nextToken();
- if (token == null)
- break;
- if (JsonToken.FIELD_NAME.equals(token) && "id".equals(parser.getCurrentName())) {
- token = parser.nextToken();
- System.out.println(parser.getText());
- }
- }
- }
- }
- }
Json生成
- public static void main(String[] args) throws IOException {
- JsonFactory factory = new JsonFactory();
- JsonGenerator generator = factory.createGenerator(new BufferedOutputStream(System.out));
-
- generator.writeStartObject();
- generator.writeFieldName("title");
- generator.writeString("Free Music Archive - Albums");
- generator.writeFieldName("dataset");
- generator.writeStartArray();
- generator.writeStartObject();
- generator.writeStringField("album_title", "A.B.A.Y.A.M");
- generator.writeEndObject();
- generator.writeEndArray();
- generator.writeEndObject();
-
-
- generator.close();
- }
Tree Mode
如果你不想为你的Json结构写一个class的话,Tree Mode是一个很好的选择。
JSON生成
- public static void main(String[] args) throws IOException {
-
- JsonNodeFactory factory = new JsonNodeFactory(false);
-
-
- JsonFactory jsonFactory = new JsonFactory();
- JsonGenerator generator = jsonFactory.createGenerator(System.out);
- ObjectMapper mapper = new ObjectMapper();
-
-
- ObjectNode node1 = factory.objectNode();
- ObjectNode node2 = factory.objectNode();
- node1.put("A", "a");
- node1.put("B", "b");
- node2.set("C", node1);
-
-
- ObjectNode root = factory.objectNode();
- root.put("root", "root");
- root.set("children", node2);
- mapper.writeTree(generator, root);
-
- }
Json解析
- public static void main(String[] args) throws Exception {
- ObjectMapper mapper = new ObjectMapper();
-
- JsonNode node = mapper.readTree("{\"root\":\"root\",\"children\":{\"C\":{\"A\":\"a\",\"B\":\"b\"}}}");
-
- System.out.println("node JsonNodeType:" + node.getNodeType());
-
- System.out.println("node is containerNode ? " + node.isContainerNode());
-
- Iterator<String> fieldNames = node.fieldNames();
- while (fieldNames.hasNext()) {
- String fieldName = fieldNames.next();
- System.out.println(fieldName + " ");
- }
- System.out.println(node.get("root").isContainerNode());
- }
总结
这只是基本的用法,其他的如果有用到,再继续添加进来。