开源工具-Json 解析器 Jackson 的使用

Json已经成为当前服务器与 WEB 应用之间数据传输的公认标准。Java 中常见的 Json 类库有 Gson、JSON-lib 和 Jackson 等。相比于其他的解析工具,Jackson 简单易用,不依赖于外部jar 包,而且更新速度比较快。其也是 SpringMVC 框架 json 格式化输出的默认实现。

Jackson fasterxml 和 codehaus 的区别

他们是 Jackson 的两大分支。从 2.0 版本开始,Jackson 开始改用新的包名 com.fasterxml.jackson;其源代码也托管到了 Github(FasterXML/Jackson)。1.x 版本现在只提供 bug-fix 。另外版本 1 和版本 2 的 artifactId 也不相同。 在使用的过程中需要注意!

Jackson fasterxml 的结构

Jackson 主要有三部分组成,除了三个模块之间存在依赖,不依赖任何外部 jar 包。三个模块的 作用及 artifactId 如下:

  • jackson-core: 核心包
  • jackson-annotations : 注解包
  • jackson-databind : 数据绑定(依赖 coreannotations

使用方式

Jackson 提供了三种 json 处理方式:

  • Streaming API : 其他两种方式都依赖于它而实现,如果要从底层细粒度控制 json 的解析生成,可以使用这种方式;
  • Tree Model : 通过基于内存的树形结构来描述 json 数据。json 结构树由 JsonNode 组成。不需要绑定任何类和实体,可以方便的对 JsonNode 来进行操作。
  • Data Binding : 最常用的方式,基于属性的 get 和 set方法以及注解来实现 JavaBean 和 json 的互转,底层实现还是 Streaming API.

代码示例

Streaming API示例

package com.maolv.oschina;

import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

/**
 * Jackson 流处理APi处理
 */
public class JacksonStreamAPITest {

    private JsonFactory factory;
    private JsonGenerator jsonGenerator;

    @Before
    public void init() throws Exception {
        factory = new JsonFactory();
        // 工厂全局设置
        factory.disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES);
        // 设置解析器
        factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
        // 设置生成器
        factory.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
        // 设置输出到console
        jsonGenerator = factory.createGenerator(System.out);
        // 覆盖上面的设置
        jsonGenerator.disable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
    }

    @Test
    public void testGenerator() throws Exception {
        String str = "hello,world!jackson!";
        // 输出字节
        jsonGenerator.writeBinary(str.getBytes());
        // 输出布尔型
        jsonGenerator.writeBoolean(true);
        // null
        jsonGenerator.writeNull();
        // 输出字符型
        jsonGenerator.writeNumber(2.2f);
        // 使用Raw方法会执行字符中的特殊字符
        jsonGenerator.writeRaw("\tc");
        // 输出换行符
        jsonGenerator.writeRaw("\r\n");

        // 构造Json数据
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("message", "Hello World!");
        jsonGenerator.writeArrayFieldStart("names");
        jsonGenerator.writeString("周杰伦");
        jsonGenerator.writeString("王力宏");
        jsonGenerator.writeEndArray();
        jsonGenerator.writeEndObject();
    }

    @Test
    public void testParser() throws Exception {
        String testStr = "{\"message\":\"Hello World!\",\"names\":[\"周杰伦\",\"王力宏\"]}";
        JsonParser p = factory.createParser(testStr);

        JsonToken t = p.nextToken();
        List<String> names = new ArrayList<String>();
        if ( t != JsonToken.START_OBJECT){
            System.out.println("Json格式不正确!");
        }
        while (t != JsonToken.END_OBJECT){
            if (t == JsonToken.FIELD_NAME && "message".equals(p.getCurrentName())){
                t =  p.nextToken();
                String message = p.getText();
                System.out.printf("My message to you is %s!\n", message);
            }
            if (t == JsonToken.FIELD_NAME && "names".equals(p.getCurrentName())){
                t = p.nextToken();
                while (t != JsonToken.END_ARRAY){
                    if (t == JsonToken.VALUE_STRING){
                        String name = p.getValueAsString();
                        names.add(name);
                    }
                    t = p.nextToken();
                }
            }
            t = p.nextToken();
        }
        System.out.println(names.toString());
        p.close();
    }

    @After
    public void close() throws Exception {
        jsonGenerator.close();
    }
}

运行结果:

"aGVsbG8sd29ybGQhamFja3NvbiE=" true null 2.2	c
{"message":"Hello World!","names":["周杰伦","王力宏"]}

Tree Model示例

package com.maolv.oschina;

import org.junit.Before;
import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * Jackson Tree Model解析生成示例
 */
public class JacksonTreeModelTest {

    private ObjectMapper objectMapper;

    @Before
    public void init() {
        objectMapper = new ObjectMapper();
        // 如果为空则不输出
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        // 对于空的对象转json的时候不抛出错误
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁用序列化日期为timestamps
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 禁用遇到未知属性抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 视空字符传为null
        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

        // 低层级配置
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        // 允许属性名称没有引号
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 取消对非ASCII字符的转码
        objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false);

    }

    @Test
    public void testTreeModel() throws Exception {
        JsonNodeFactory nodeFactory = objectMapper.getNodeFactory();
        // 创建一个model
        ObjectNode node = nodeFactory.objectNode();
        node.put("age", 18);
        // 新增
        node.put("name", "周杰伦");
        // 如果存在同名的则是替换操作
        node.put("age", 19);
        ArrayNode coursesNode = node.putArray("courses");
        coursesNode.add("思想政治");
        coursesNode.add("高等数学");
        // 获取节点类型
        System.out.println(node.getNodeType());
        System.out.println(coursesNode.getNodeType());
        // 移除第一个
        coursesNode.remove(0);
        // 输出
        System.out.println(node.toString());
        String jsonStr = "{\"age\":19,\"name\":\"周杰伦\",\"courses\":[\"高等数学\"]}";
        JsonNode jsonNode = objectMapper.readTree(jsonStr);
        ArrayNode arrayNode = (ArrayNode) jsonNode.withArray("courses");
        arrayNode.add("马列");
        for (int i = 0;i < arrayNode.size();i++){
            System.out.println(arrayNode.get(i).asText());
        }
        System.out.println(jsonNode.toString());

    }
}

运行结果:

OBJECT
ARRAY
{"age":19,"name":"周杰伦","courses":["高等数学"]}
高等数学
马列
{"age":19,"name":"周杰伦","courses":["高等数学","马列"]}

Data Binding 示例

package com.maolv.oschina;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Before;
import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * Jackson Data bind 解析生成示例
 */
public class JacksonDataBindTest {

    private ObjectMapper baseMapper;
    private ObjectMapper prettyMapper1;
    private ObjectMapper prettyMapper2;
    private ObjectMapper nonEmptyMapper;

    @Before
    public void init(){
        baseMapper = new ObjectMapper();
        // 对于空的对象转json的时候不抛出错误
        baseMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁用遇到未知属性抛出异常
        baseMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        baseMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        // 低层级配置
        baseMapper.configure(JsonParser.Feature.ALLOW_COMMENTS,true);
        baseMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,true);
        baseMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES,true);
        // 配置两个副本
        prettyMapper1 = baseMapper.copy();
        prettyMapper2 = baseMapper.copy();
        // 高级配置
        prettyMapper1.enable(SerializationFeature.INDENT_OUTPUT);
        prettyMapper1.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        prettyMapper1.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        // 禁用序列化日期为timestamps
        prettyMapper1.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        prettyMapper1.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII,false);
        // Json格式化展示
        prettyMapper2.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        prettyMapper2.enable(SerializationFeature.INDENT_OUTPUT);
        prettyMapper2.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII,true);
        prettyMapper2.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);

        nonEmptyMapper = new ObjectMapper();
        nonEmptyMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        nonEmptyMapper.enable(SerializationFeature.INDENT_OUTPUT);
        nonEmptyMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    @Test
    public void testReadValue() throws IOException {
        String json = "{\n" +
                "  \"name\" : \"发如雪\",\n" +
                "  \"now\" : \"2015-12-17 17:25:13\",\n" +
                "  \"sexy\" : \"MEN\"\n" +
                "}";
        TestBean testBean = nonEmptyMapper.readValue(json,TestBean.class);
        System.out.println(testBean.toString());
    }

    @Test
    public void testWriteValue() throws IOException {
        TestBean testBean = new TestBean("发如雪",Sexy.MEN);
        System.out.println(prettyMapper1.writeValueAsString(testBean));
        System.out.println(prettyMapper2.writeValueAsString(testBean));
        System.out.println(nonEmptyMapper.writeValueAsString(testBean));
    }

}
class TestBean{
    private String name;
    private String course;
    private Date now;
    private Sexy sexy;
    public TestBean(){}
    public TestBean(String name,Sexy sexy){
        this.name = name;
        this.sexy = sexy;
        this.now = new Date();
    }

    public Date getNow() {
        return now;
    }

    public void setNow(Date now) {
        this.now = now;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Sexy getSexy() {
        return sexy;
    }

    public void setSexy(Sexy sexy) {
        this.sexy = sexy;
    }

    public String getCourse() {
        return course;
    }

    public void setCourse(String course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "TestBean{" +
                "name='" + name + '\'' +
                ", course='" + course + '\'' +
                ", now=" + now +
                ", sexy=" + sexy +
                '}';
    }
}
enum Sexy{
    MEN("男","M"),WOMEN("女","W");
    private String text;
    private String code;

    private Sexy(String text,String code){
        this.text = text;
        this.code = code;
    }

    public String getText() {
        return text;
    }

    public String getCode() {
        return code;
    }

    @Override
    public String toString() {
        return "{\"text\":\""+getText()+"\",\"code\":\""+getCode()+"\"}";
    }
}

posted @ 2015-12-17 17:32  飞翔的花狸猫  阅读(20534)  评论(0编辑  收藏  举报