据说Streaming API 的效率是最高的,写入的时候直接调用JsonGenerator.writexxxfield,最后一个close就flush到文件了。不过读取的时候则比较蠢(?),需要一个while循环,不断地将文件里的字段与对象的字段作是否等于的比较,然后setField。
这次Demo里需要用到User.class,在第一个Demo的基础上改好了:
项目结构:

package com.hankcs;
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Main
{
public static void main(String[] args) throws IOException
{
JsonFactory f = new JsonFactory();
JsonGenerator g = f.createJsonGenerator(new File("user.json"), JsonEncoding.UTF8);
g.writeStartObject();
g.writeObjectFieldStart("name");
g.writeStringField("first", "Joe");
g.writeStringField("last", "Hankcs");
g.writeEndObject(); // for field 'name'
g.writeStringField("gender", "MALE");
g.writeBooleanField("verified", false);
g.writeFieldName("userImage"); // no 'writeBinaryField' (yet?)
byte[] binaryData = {0x1, 0x2, 0x3};
g.writeBinary(binaryData);
g.writeEndObject();
g.close(); // important: will force flushing of output, close underlying output stream
// 解析
// JsonFactory f = new JsonFactory();
JsonParser jp = f.createJsonParser(new File("user.json"));
User user = new User();
jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
while (jp.nextToken() != JsonToken.END_OBJECT)
{
String fieldname = jp.getCurrentName();
jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
if ("name".equals(fieldname))
{ // contains an object
User.Name name = new User.Name();
while (jp.nextToken() != JsonToken.END_OBJECT)
{
String namefield = jp.getCurrentName();
jp.nextToken(); // move to value
if ("first".equals(namefield))
{
name.setFirst(jp.getText());
}
else if ("last".equals(namefield))
{
name.setLast(jp.getText());
}
else
{
throw new IllegalStateException("Unrecognized field '" + fieldname + "'!");
}
}
user.setName(name);
}
else if ("gender".equals(fieldname))
{
user.setGender(User.Gender.valueOf(jp.getText()));
}
else if ("verified".equals(fieldname))
{
user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
}
else if ("userImage".equals(fieldname))
{
user.setUserImage(jp.getBinaryValue());
}
else
{
throw new IllegalStateException("Unrecognized field '" + fieldname + "'!");
}
}
jp.close(); // ensure resources get cleaned up timely and properly
System.out.println(user);
}
}
输出:
User{_gender=MALE, _name=Name{_first='Joe', _last='Hankcs'}, _isVerified=false, _userImage=[1, 2, 3]}
对于数组类型的JSON数据,则简单了不少:
// 对于数组有更好的方法
ObjectMapper mapper = new ObjectMapper();
String json = "[{\"foo\": \"bar\"},{\"foo\": \"biz\"}]";
jp = f.createJsonParser(json);
// advance stream to START_ARRAY first:
jp.nextToken();
// and then each time, advance to opening START_OBJECT
while (jp.nextToken() == JsonToken.START_OBJECT)
{
Foo foobar = mapper.readValue(jp, Foo.class);
// process
System.out.println(foobar);
// after binding, stream points to closing END_OBJECT
}
输出:
Foo{foo='bar'}
Foo{foo='biz'}
项目源码:http://pan.baidu.com/s/1nt8sFDB
参考:http://wiki.fasterxml.com/JacksonInFiveMinutes#Full_Data_Binding_.28POJO.29_Example
知识共享署名-非商业性使用-相同方式共享:码农场 » 五分钟Jackson入门(四) JSON Streaming API (附项目源码)
码农场
小数如何处理,保留2位 BigDecimal类型的