jackson官方快速入门文档
官方地址: http://jackson.codehaus.org/
http://wiki.fasterxml.com/JacksonInFiveMinutes
http://wiki.fasterxml.com/JacksonDocumentation
Inspired by the quality and variety of XML tooling available for the Java platform (StAX, JAXB, etc.), the Jackson is a multi-purpose
Java library for processing JSON. Jackson aims to be the best possible combination of fast, correct, lightweight, and ergonomic for developers.
This page gives an overview of Jackson's capabilities.
目录
JSON Three Ways
Jackson offers three alternative methods (one with two variants) for processing JSON:
Streaming API (aka "Incremental parsing/generation") reads and
writes JSON content as discrete events.org.codehaus.jackson.JsonParser reads, org.codehaus.jackson.JsonGenerator writes.
Inspired by the StAX API.
Tree Model provides a mutable in-memory tree representation of a
JSON document.org.codehaus.jackson.map.ObjectMapper can build trees; trees
consist of JsonNode nodes.- The tree model is similar to the XML DOM.
Data Binding converts JSON to and from POJOs based either on property
accessor conventions or annotations.There are two variants: simple and full data binding
Simple data binding means converting to and from Java Maps, Lists, Strings, Numbers, Booleans and nulls
Full data binding means converting to and from any Java bean type (as well as "simple" types mentioned above)
org.codehaus.jackson.map.ObjectMapper performs the marshalling
(writing JSON) and unmarshalling (reading JSON) for both variants.Inspired by the annotation-based (code-first) variant of JAXB.
From usage perspective, one way to summarize these 3 methods is:
Streaming API is best performing (lowest overhead, fastest read/write;
other 2 methods build on it)Data Binding is often most convenient
Tree Model is most flexible
Given these properties, let's consider these in the reverse order, starting with what is usually the most natural and convenient method for Java developers: Jackson
Data Binding API.
Examples
Full Data Binding (POJO) Example
Jackson's org.codehaus.jackson.map.ObjectMapper "just works" for mapping JSON data into plain old Java objects ("POJOs"). For example, given JSON data
{
"name" : { "first" : "Joe", "last" : "Sixpack" },
"gender" : "MALE",
"verified" : false,
"userImage" : "Rm9vYmFyIQ=="
}
It takes two lines of Java to turn it into a User instance:
1 ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
2 User user = mapper.readValue(new File("user.json"), User.class);
Where the User class looks something like this (from anentry on Tatu's blog):
1 public class User {
2 public enum Gender { MALE, FEMALE };
3
4 public static class Name {
5 private String _first, _last;
6
7 public String getFirst() { return _first; }
8 public String getLast() { return _last; }
9
10 public void setFirst(String s) { _first = s; }
11 public void setLast(String s) { _last = s; }
12 }
13
14 private Gender _gender;
15 private Name _name;
16 private boolean _isVerified;
17 private byte[] _userImage;
18
19 public Name getName() { return _name; }
20 public boolean isVerified() { return _isVerified; }
21 public Gender getGender() { return _gender; }
22 public byte[] getUserImage() { return _userImage; }
23
24 public void setName(Name n) { _name = n; }
25 public void setVerified(boolean b) { _isVerified = b; }
26 public void setGender(Gender g) { _gender = g; }
27 public void setUserImage(byte[] b) { _userImage = b; }
28 }
Marshalling back to JSON is similarly straightforward:
mapper.writeValue(new File("user-modified.json"), user);
For fancier data binding (e.g., unmarshalling formatted dates into java.util.Date), Jackson provides annotations to customize the marshalling and unmarshalling process.
"Raw" Data Binding Example
(also known as "Untyped", or sometimes "simple" data binding)
In cases where you do not have (and don't want to create) specific Java classes to bind JSON to/from, "Untyped data binding" may be a better approach. It is used same way as full data binding, except that the formal binding type is specified simply as Object.class (or Map.class, List.class, String[].class if
more specific typing is wanted). So the earlier binding of JSON that represent User data could have been done by:
Map<String,Object> userData = mapper.readValue(new File("user.json"), Map.class);
and userData would be like one we would explicit construct by:
1 Map<String,Object> userData = new HashMap<String,Object>();
2 Map<String,String> nameStruct = new HashMap<String,String>();
3 nameStruct.put("first", "Joe");
4 nameStruct.put("last", "Sixpack");
5 userData.put("name", nameStruct);
6 userData.put("gender", "MALE");
7 userData.put("verified", Boolean.FALSE);
8 userData.put("userImage", "Rm9vYmFyIQ==");
This obviously works both ways: if you did construct such a Map (or bind from JSON and modify), you could write out just as before, by:
mapper.writeValue(new File("user-modified.json"), userData);
How does this work? By specifying Map.class, we do not specify generic key/value types. But ObjectMapper does know how to bind JSON data to and from Maps (and Lists, arrays, wrapper types), and does just that. Fundamentally JSON data has no
"real" type as far as Jackson is concerned -- if it can be properly mapped to a type you give, it will be mapped.
Concrete Java types that Jackson will use for simple data binding are:
|
JSON Type |
Java Type |
|
object |
LinkedHashMap<String,Object> |
|
array |
ArrayList<Object> |
|
string |
String |
|
number (no fraction) |
Integer, Long or BigInteger (smallest applicable) |
|
number (fraction) |
Double (configurable to use BigDecimal) |
|
true|false |
Boolean |
|
null |
null |
Data Binding with Generics
In addition to binding to POJOs and "simple" types, there is one additional variant: that of binding to generic (typed) containers. This case requires special handling due to so-called Type Erasure (used by Java to
implement generics in somewhat backwards compatible way), which prevents you from using something like Collection<String>.class (which does not compile).
So if you want to bind data into a Map<String,User> you will need to use:
Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });
where TypeReference is only needed to pass generic type definition (via anynomous inner class in this case): the important part is <Map<String,User>> which defines type to bind to.
If you don't do this (and just pass Map.class), call is equivalent to binding to Map<?,?> (i.e. "untyped" Map), as explained above.
UPDATE: As an alternative, version 1.3 also allows programmatic construction of types by using TypeFactory.
Tree Model Example
Yet another way to get Objects out of JSON is to build a tree. This is similar to DOM trees for XML. The way Jackson builds trees is to use basic JsonNode base class, which exposes read access that is usually needed. Actual node types used are sub-classes;
but the sub-type only needs to be used when modifying trees.
Trees can be read and written using either Streaming API (see below), or using ObjectMapper.
With ObjectMapper, you will do something like:
1 ObjectMapper m = new ObjectMapper();
2 // can either use mapper.readTree(source), or mapper.readValue(source, JsonNode.class);
3 JsonNode rootNode = m.readTree(new File("user.json"));
4 // ensure that "last name" isn't "Xmler"; if is, change to "Jsoner"
5 JsonNode nameNode = rootNode.path("name");
6 String lastName = nameNode.path("last").getTextValue().
7 if ("xmler".equalsIgnoreCase(lastName)) {
8 ((ObjectNode)nameNode).put("last", "Jsoner");
9 }
10 // and write it out:
11 m.writeValue(new File("user-modified.json"), rootNode);
Or if you want to construct a Tree (for the User example) from scratch, you can do:
1 TreeMapper treeMapper = new TreeMapper();
2 ObjectNode userOb = treeMapper.objectNode();
3 Object nameOb = userRoot.putObject("name");
4 nameOb.put("first", "Joe");
5 nameOb.put("last", "Sixpack");
6 userOb.put("gender", User.Gender.MALE.toString());
7 userOb.put("verified", false);
8 byte[] imageData = getImageData(); // or wherever it comes from
9 userOb.put("userImage", imageData);
(NOTE: with Jackson 1.2 you can use ObjectMapper directly, using ObjectMapper.createObjectNode()
to create userOb -- above example will work with JAckson 1.0 and 1.1)
Streaming API Example
And finally, there is the third way: turbo-charged, high-performance method known as Streaming API (aka incremental mode, since content is read and written incrementally).
Just for fun, let's implement the writing functionality (equivalent to earlier examples) using "raw" Streaming API: WriteJSON.java
1 JsonFactory f = new JsonFactory();
2 JsonGenerator g = f.createJsonGenerator(new File("user.json"));
3
4 g.writeStartObject();
5 g.writeObjectFieldStart("name");
6 g.writeStringField("first", "Joe");
7 g.writeStringField("last", "Sixpack");
8 g.writeEndObject(); // for field 'name'
9 g.writeStringField("gender", Gender.MALE);
10 g.writeBooleanField("verified", false);
11 g.writeFieldName("userImage"); // no 'writeBinaryField' (yet?)
12 byte[] binaryData = ...;
13 g.writeBinary(binaryData);
14 g.writeEndObject();
15 g.close(); // important: will force flushing of output, close underlying output stream
Not horribly bad (esp. compared to amount of work needed for writing, say, equivalent XML content), but certainly more laborious than basic Object mapping.
On the other hand, you do have full control over each and every detail. And overhead is minimal: this is still a bit faster than using ObjectMapper; not a whole lot (perhaps 20-30% faster in common cases), but still. And perhaps most importantly, output
is done in streaming manner: except for some buffering, all content will be written out right away. This means that memory usage is also minimal.
How about parsing, then? Code could look something like:
1 JsonFactory f = new JsonFactory();
2 JsonParser jp = f.createJsonParser(new File("user.json"));
3 User user = new User();
4 jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
5 while (jp.nextToken() != JsonToken.END_OBJECT) {
6 String fieldname = jp.getCurrentName();
7 jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
8 if ("name".equals(fieldname)) { // contains an object
9 Name name = new Name();
10 while (jp.nextToken() != JsonToken.END_OBJECT) {
11 String namefield = jp.getCurrentName();
12 jp.nextToken(); // move to value
13 if ("first".equals(namefield)) {
14 name.setFirst(jp.getText());
15 } else if ("last".equals(namefield)) {
16 name.setLast(jp.getText());
17 } else {
18 throw new IllegalStateException("Unrecognized field '"+fieldname+"'!");
19 }
20 }
21 user.setName(name);
22 } else if ("gender".equals(fieldname)) {
23 user.setGender(User.Gender.valueOf(jp.getText()));
24 } else if ("verified".equals(fieldname)) {
25 user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
26 } else if ("userImage".equals(fieldname)) {
27 user.setUserImage(jp.getBinaryValue());
28 } else {
29 throw new IllegalStateException("Unrecognized field '"+fieldname+"'!");
30 }
31 }
32 jp.close(); // ensure resources get cleaned up timely and properly
which is quite a bit more than you'll use with data binding.
One final trick: it is also possible to use data binding and tree model directly from JsonParser and JsonGenerator. To do this, have a look at methods:
JsonParser.readValueAs()
JsonParser.readValueAsTree()
JsonGenerator.writeObject()
JsonGenerator.writeTree()
which do about what you might expect them to do.
The only (?) trick is that you MUST make sure you use org.codehaus.jackson.map.MappingJsonFactory for constructing "data-binding capable" parser and generator instances (instead of basicorg.codehaus.jackson.JsonFactory).
Streaming API Example 2: arrays
(as contributed by Ransom Briggs)
Let's consider following POJO:
1 public class Foo {
2 public String foo;
3 }
and sample JSON stream of:
String json = [{\"foo\": \"bar\"},{\"foo\": \"biz\"}]";
while there are convenient ways to work on this with databinding (see ObjectReader.readValues() for details), you can easily use
streaming to iterate over stream, bind individual elements as well:
1 JsonFactory f = new JsonFactory();
2 JsonParser jp = f.createJsonParser(json);
3 // advance stream to START_ARRAY first:
4 jp.nextToken();
5 // and then each time, advance to opening START_OBJECT
6 while (jp.nextToken() == JsonToken.START_OBJECT)) {
7 Foo foobar = mapper.readValue(jp, Foo.class);
8 // process
9 // after binding, stream points to closing END_OBJECT
10 }
Next Steps
You may want to check out rest of JacksonDocumentation for more inspiration.
jackson官方快速入门文档的更多相关文章
- UE4官方行为树快速入门文档解析和修改
近学习了UE4官方文档的行为树快速入门指南,发现里面的部分逻辑稍稍有点混乱和重叠,于是加入了自己的想法,修改了部分行为树逻辑,优化了其AI寻路能力. 初始的基本操作和资源创建同官方文档一样:1个Fol ...
- ThinkPHP5 快速入门文档
一. 5.0版本采用模块化的设计架构,默认的应用目录下面只有一个index模块目录,如果我要添加新的模块可以使用控制台命令来生成. 切换到命令行模式下,进入到应用根目录并执行如下指令: php thi ...
- Python快速入门文档
前言 此文本质为本人学习Python过程中的笔记,部分地方叙述表达可能不够清晰,欢迎留言. (本文适合有一定程序语言基础的读者阅读(最好是c语言)) 一.基本语法 1.框架: (1)以缩进表示层次所属 ...
- Apache BeanUtils 1.9.2 官方入门文档
为什么需要Apache BeanUtils? Apache BeanUtils 是 Apache开源软件组织下面的一个项目,被广泛使用于Spring.Struts.Hibernate等框架,有数千个j ...
- 【简明翻译】Hibernate 5.4 Getting Started Guide 官方入门文档
前言 最近的精力主要集中在Hibernate上,在意识到Hibernate 5 的中文资料并不多的时候,我不得不把目光转向Hibernate的官方doc,学习之余简要翻一下入门文档. 原文地址:htt ...
- vuex最简单、最直白、最全的入门文档
前言 我们经常用element-ui做后台管理系统,经常会遇到父组件给子组件传递数据,下面一个简单的例子,点击按钮,把弹框显示变量数据通过子组件的props属性传递,子组件通过$emit事件监听把数据 ...
- Babylon.js官方性能优化文档中文翻译
在这里列出Babylon.js官方性能优化文档的中英文对照,并在CardSimulate项目里对其中的一些优化方法进行实践. How To 如何 Optimize your scene 优化你的场景 ...
- 【Elastic-1】ELK基本概念、环境搭建、快速开始文档
TODO 快速开始文档 SpringBoot整合ELK(Logstash收集日志.应用主动向ES写入) ELK接入Kafka 基本概念 ElasticSearch 什么是ElasticSearch? ...
- 数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
随机推荐
- cookie设置保存用户名,填入中文名之后出现的错误500问题
对于问题发生的原因以后再来补充: 解决方法就是在dologin.jsp当中使用URLEncode工具类,这个工具类在java的net包当中 <一>用户浏览器-->jsp 的过程 1 ...
- JavaScript中的匿名函数及函数的闭包
1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种: ...
- Java异常处理机制 try-catch-finally 剖析
Java拥有着强大的异常处理机制,最近初步学习了下,感觉内容还是挺多的,特此来将自己的理解写出来与大家分享. 一. 在Java代码code中,由于使用Myeclipse IDE,可以自动提醒用户哪里有 ...
- 初识UML类图--类之间关系
前言 最近有打算学习一下设计模式,所以就去看了园子里面左潇龙大哥的设计模式文章,看完之后只有一个感觉,我啥时候也能写出来这么牛逼的文章啊,但是我这语文老师死的早的人还是算了,但是设计模式还是要学的,这 ...
- spring入门(五)【springMVC环境搭建】
springMVC作为spring的一个WEB组件,是一个MVC的思想,减少了WEB开发的难度,现介绍springMVC环境的搭建,具体的原理放在后面介绍.用过框架的朋友都知道要在WEB项目中使用一个 ...
- SOA实践之基于服务总线的设计
在上文中,主要介绍了SOA的概念,什么叫做“服务”,“服务”应该具备哪些特性.本篇中,我将介绍SOA的一种很常见的设计实践--基于服务总线的设计. 基于服务总线的设计 基于总线的设计,借鉴了计算机内部 ...
- 一起谈谈MD5加密算法
MD5是一个安全的散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程不可逆:所以要解密MD5没有现成的算法,只能用穷举法,把可能出现的明文,用MD5算法散列之后 ...
- [翻译]用 Puppet 搭建易管理的服务器基础架构(2)
我通过伯乐在线翻译了一个Puppet简明教程,一共分为四部分,这是第二部分. 原文地址:http://blog.jobbole.com/87680/ 本文由 伯乐在线 - Wing 翻译,黄利民 校稿 ...
- 文章转载利用border、transparent实现微风
微风效果预览 微风源码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- WePayUI 快快尝鲜体验
好久没有更新博客了... 时间真的很快~~~ 不废话了..干货会直接上~~~ WePayUI是什么 WePayUI 由微信支付为服务商和商户量身打造,用于快速制作符合微信支付规范的Web页面.WePa ...