利用jackson实现Json序列化和反序列化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ymaini/article/details/82470050

简介

在日常开发中,经常利用JSON作为数据传输的格式,为此JSON序列化(将对象转换为JSON字符串)和反序列化(将JSON字符串转换指定的数据类型)经常用到。

本文主要介绍利用fasterxml.jackson实现JSON序列化和反序列化,并针对碰到到Unrecognized field的问题进行解决。

Gradle依赖

利用fasterxml.jackson依赖jackson-core, jackson-databindjackson-annotations,在build.gradle文件中添加依赖, 示例如下:

dependencies {
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5'
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.5'
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5'


    }

序列化和反序列化实现

JSON工具类

我们构造一个JSON工具类,实现JSON序列化和反序列化, 主要用到的类为com.fasterxml.jackson.databind.ObjectMapper, 代码示例如下:

package com.notepad.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by YM on 2017/6/11.
 */
public class JsonSerializer {

    /**
     * JSON序列化
     *
     * @param object 对象
     * @return JSON字符串
     */
    public static String serialize(Object object) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * JSON字符串反序列化
     *
     * @param jsonStr JSON字符串
     * @return a Map
     */
    public static Map deserialize(String jsonStr) {
        try {
            return deserialize(jsonStr, Map.class);
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap();
        }
    }

    public static <T> T deserialize(String jsonStr, Class<T> classType) throws Exception {
        return new ObjectMapper().readValue(jsonStr, classType);
    }
}

Entity

为测试我们编写的JSON工具类, 定义一个Entity对象。

为了构建的Entity对象被JSON工具类操作, 关于Entity有几点说明:

  1. Entity对象必须有默认构造函数
  2. 成员变量必须有对应的Setter方法
  3. 可选: 可通过@JsonProperty自定义序列化和反序列化对应的字符的名称,如@JsonProperty(“UID”),则序列化时uid字段显示为UID,同理反序列化时找到字符串中UID对应的值,复制给uid。
  4. 可选:可通过@JsonIgnore注解,过滤掉不需要进行序列化的成员变量。

    示例如下:

package com.notepad.thinkingnote.domain;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Description: 实体定义
 * <p>
 * Create:      2018/9/6 22:37
 *
 * @author Yang Meng
 */
public class Entity {

    public Entity() {}

    public Entity(String uid, String name) {
        this.uid = uid;
        this.name = name;
    }

    /** 实体标识符 */
    @JsonProperty("UID")
    private String uid;

    @JsonProperty("name")
    private String name;

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getUid() {
        return uid;
    }

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

    public String getName() {
        return name;
    }
}

单元测试

编写单元测试,测试Entity的序列化和反序列化, 示例如下:

package com.notepad.thinkingnote.domain;

import com.notepad.util.JsonSerializer;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Description: 实体序列化和反序列化单测
 * <p>
 * Create:      2018/9/6 22:41
 *
 * @author Yang Meng
 */
public class EntityTest {

    @Test
    public void testSerialize() throws Exception {
        Entity entity = new Entity("James", "James");
        System.out.println(JsonSerializer.serialize(entity));
    }


    @Test
    public void testDeserialize() throws Exception {
        String test = "{\"UID\":\"James\",\"name\":\"James\"}";
        Entity entity = JsonSerializer.deserialize(test, Entity.class);
        System.out.println(entity.getUid() + ":" + entity.getName());
    }
}

输出结果如下:

// entity的序列化结果, 显示字段UID
{"UID":"James","name":"James"}

// entity的序列化结果
James:James

UnrecognizedPropertyException

通过上面的介绍, 我们基本了解了JSON的序列化和反序列化,不过有时我们会遇到一种问题。

考虑这样一种情况,我们针对Http接口返回的JSON字符串,构建了一个具体的Entity对象,但是Http接口中突然增加了一个字段type,如果按照上述的方法构造,这时会出现什么问题?

再编写一个单测样例:

@Test
    public void testDeserialize() throws Exception {
        String test = "{\"UID\":\"James\",\"name\":\"James\", \"type\":\"entity\"}";
        Entity entity = JsonSerializer.deserialize(test, Entity.class);
        System.out.println(entity.getUid() + ":" + entity.getName());
    }

出现UnrecognizedPropertyException异常:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type" ....

即对于新添加的type字符无法识别。如何解决这个问题呢?我们这里提供2种方法。

JsonIgnoreProperties注解

利用fasterxml.jackson提供的@JsonIgnoreProperties注解,针对无法识别的属性进行过滤。这里主要是修改需要进行反序列化的对象Entity,示例如下:

// 针对无法识别的属性进行过滤
@JsonIgnoreProperties(ignoreUnknown = true)
public class Entity {...}

DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

方法1的修改需要对每一个需要进行反序列化的类进行修改, 不太方便。

方法2通过修改JSON工具类的反序列化方法,设置DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES的值为false, 可以仅一次修改就适用全部对象。

示例如下:

public static <T> T deserialize(String jsonStr, Class<T> classType) throws Exception {
        // 添加configure, 设置DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES为false
        // 则对于无法识别的属性直接过滤    
        return new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .readValue(jsonStr, classType);
    }

总结

本文主要介绍利用jackson实现Json序列化和反序列化,并给出了解决UnrecognizedPropertyException异常的2种方法。

猜你喜欢

转载自blog.csdn.net/ymaini/article/details/82470050