据说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类型的