Json已经成为当前服务器与 WEB 应用之间数据传输的公认标准。目前java json解析工具有阿里的fastjson,google的GSON,以及SpringMVC 默认的解析工具Jackson。SpringBoot默认自带是jackson,网上有很多json转换速率的比对,如jackson,阿里的fastjson等,不过jackson足够使用了.

1、 在pom.xml引依赖

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.5</version>
</dependency>

一般情况下,SpringBoot开发web应用会引用spring-boot-starter-web依赖包,而这个依赖包会默认引用

<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.8.0</version>
</dependency>
<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.8.7</version>
</dependency>
<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.7</version>
</dependency>

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

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

而 jackson-databind 依赖另外两个,所以单独引用时,只引用 jackson-databind 就可以使用了.

2、 使用

实体类:

package cn.sakura521.jacksondemo.entity;

import com.fasterxml.jackson.annotation.JsonFormat;


import java.util.Date;

public class User {
    private String name;
    //不JSON序列化加    @JsonIgnore
//    @JsonIgnore
    private Integer age;
    //格式化日期属性
    @JsonFormat(pattern = "yyyy年MM月dd日")
    private Date date;
    private String url;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", date=" + date +
                ", url='" + url + '\'' +
                '}';
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}

序列化

ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。

示例:

package cn.sakura521.jacksondemo;

import cn.sakura521.jacksondemo.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class jacksonDemo {

    public static void main(String[] args) throws ParseException, IOException {
        User user = new User();
        user.setName("小坏孩");
        user.setAge(21);
        user.setUrl("https://www.sakura521.cn");

        //当前时间
        Date date = new Date();
        user.setDate(date);
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        user.setDate(dateFormat.parse("2020-03-04"));

        ObjectMapper mapper = new ObjectMapper();

        //类转JSON
        //输出结果是:{"name":"小坏孩","age":21,"date":1583251200000,"url":"www.sakura521.cn"}
        //User类Date加上(格式化日期属性)@JsonFormat(pattern = "yyyy年MM月dd日")后
        //结果为:{"name":"小坏孩","age":21,"date":"2020年03月04日","url":"www.sakura521.cn"}
        String json = mapper.writeValueAsString(user);
        System.out.println(json);

        //集合转JSON
        //输出结果是:[{"name":"小坏孩","age":21,"date":1583251200000,"url":"www.sakura521.cn"}]
        //User类Date加上(格式化日期属性)@JsonFormat(pattern = "yyyy年MM月dd日")后
        //结果为:[{"name":"小坏孩","age":21,"date":"2020年03月04日","url":"www.sakura521.cn"}]
        List<User> users = new ArrayList<>();
        users.add(user);
        String jsonlist = mapper.writeValueAsString(users);
        System.out.println(jsonlist);

    }


}

反序列化

package cn.sakura521.jacksondemo;

import cn.sakura521.jacksondemo.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class jacksonDemo {

    public static void main(String[] args) throws ParseException, IOException {

        String json1 = "{\"name\":\"小坏孩\",\"age\":21,\"date\":1583251200000,\"url\":\"www.sakura521.cn\"}";


        /**
         * ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。
         */
        //输出结果:User{name='小坏孩', age=21, date=Wed Mar 04 00:00:00 CST 2020, url='www.sakura521.cn'}
        User user1 = mapper.readValue(json1,User.class);
        System.out.println(user1);

    }


}

JSON注释

Jackson提供了一系列注解,方便对JSON序列化和反序列化进行控制,下面介绍一些常用的注解。

@JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。

@JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。

@JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty("name")。

示例:

    private String name;
    //不JSON序列化加    @JsonIgnore
//    @JsonIgnore
    private Integer age;
    //格式化日期属性
    @JsonFormat(pattern = "yyyy年MM月dd日")
    private Date date;
    private String url;

readTree

在jackson中,有些场景下,在实现一些基础服务和拦截器的时候,我们可能需要在不知道JSON字符串所属对象类型的情况下,对JSON字符串中的某些属性进行遍历和修改,比如,设置或查询一些报文头字段。

在jackson中,使用最多的jsonNode抽象类并没有提供修改节点值的方法,而是在ObjectNode节点中提供修改接口,这个节点在官方说明中,一般用户创建新的节点。

在ObjectNode节点中提供修改接口(put),JsonNode提供查询的接口:

JsonNode rootNode = mapper.readTree(jsonStr);//jsonStr是一个json字符串 
JsonNode targetNode = null;
targetNode = rootNode.findValue("rpcMsgId"); // 查找第一级的rpcMsgId属性,如果属性不存在,则返回null,属性值如果为明确的null,返回NullNode,否则返回正常的JsonNode 
// 注:JsonNode还提供了find/path/get等获取节点的方法,但是这三种方法都不能明确的区分节点不存在、为明确的null。所以,应该使用findValue方法。

如果只是纯粹的遍历和类似JsonTree的构造,网上有各种文章,主要是对原json中属性的修改。可通过如下的方式进行修改:

((ObjectNode)targetNode).put("rpcMsgId","abcdefg1234567890"); 
// 通过强制转换为ObjectNode,就可以对当前节点进行修改,其他的XXXNode均没有提供相关的API接口 String modifiedJsonStr = mapper.writeValueAsString(rootNode); // 最后重新生成json字符串,这跟dom4j修改xml一样,只能重新生成,内置不支持直接修改原文件

//完整的代码
JsonNode node = mapper.readTree(jsonStr);
JsonNode node1 = node.findValue("spiderPacketHead");
ObjectNode node2 = (ObjectNode) node1;
node2.put("rpcMsgId", "abc"); 

修改后的工具类JsonUtils

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * <b>Description:</b> json转换工具类 <br>
 *
 * @author luozhen
 * @version 1.0
 * @Note <b>ProjectName:</b> MySpringBoot <br>
 *       <b>PackageName:</b> com.luozhen.util <br>
 *       <b>ClassName:</b> JacksonActivity <br>
 *       <b>Date:</b> 2018年5月24日 下午12:50:59
 */

public class JsonUtils {

    /**
     * ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。
     * ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
     * writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中。
     * writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
     * writeValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组。
     * writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。
     */

    /**
     * 初始化变量
     */
    private static ObjectMapper mapper = new ObjectMapper();

    static {
        // 解决实体未包含字段反序列化时抛出异常
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 对于空的对象转json的时候不抛出错误
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

        // 允许属性名称没有引号
        mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

        // 允许单引号
        mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
    }

    /**
     *
     * <b>Description:</b> 将一个object转换为json, 可以使一个java对象,也可以使集合<br>
     * <b>Title:</b> ObjectToJson<br>
     *
     * @param obj
     *            - 传入的数据
     * @return
     * @Note <b>Author:</b> luozhen <br>
     *       <b>Date:</b> 2018年5月24日 下午1:26:53 <br>
     *       <b>Version:</b> 1.0
     */
    public static String objectToJson(Object obj) {
        String json = null;
        try {
            json = mapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。
     */

    /**
     *
     * <b>Description:</b> 将json结果集转化为对象<br>
     * <b>Title:</b> jsonToClass<br>
     *
     * @param json
     *            - json数据
     * @param beanType
     *            - 转换的实体类型
     * @return
     * @Note <b>Author:</b> luozhen <br>
     *       <b>Date:</b> 2018年5月24日 下午3:26:18 <br>
     *       <b>Version:</b> 1.0
     */
    public static <T> T jsonToClass(String json, Class<T> beanType) {
        T t = null;
        try {
            t = mapper.readValue(json, beanType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     *
     * <b>Description:</b> 将json数据转换成Map<br>
     * <b>Title:</b> jsonToMap<br>
     *
     * @param json
     *            - 转换的数据
     * @return
     * @Note <b>Author:</b> luozhen <br>
     *       <b>Date:</b> 2018年5月24日 下午3:29:37 <br>
     *       <b>Version:</b> 1.0
     */
    public static Map<String, Object> jsonToMap(String json) {
        Map<String, Object> map = null;
        try {
            map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     *
     * <b>Description:</b> 将json数据转换成list <br>
     * <b>Title:</b> jsonToList<br>
     *
     * @param json
     *            - 转换的数据
     * @return
     * @Note <b>Author:</b> luozhen <br>
     *       <b>Date:</b> 2018年5月24日 下午3:28:35 <br>
     *       <b>Version:</b> 1.0
     */
    public static <T> List<T> jsonToList(String json, Class<T> beanType) {
        List<T> list = null;
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);
            list = mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     *
     * <b>Description:</b> 获取json对象数据的属性<br>
     * <b>Title:</b> findValue<br>
     *
     * @param resData
     *            - 请求的数据
     * @param resPro
     *            - 请求的属性
     * @return 返回String类型数据
     * @Note <b>Author:</b> luozhen <br>
     *       <b>Date:</b> 2018年5月31日 上午10:00:09 <br>
     *       <b>Version:</b> 1.0
     */
    public static String findValue(String resData, String resPro) {
        String result = null;
        try {
            JsonNode node = mapper.readTree(resData);
            JsonNode resProNode = node.get(resPro);
            result = JsonUtils.objectToJson(resProNode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

引用地址:

作者:渊默十三
链接:https://www.jianshu.com/p/b804874b7a69
来源:简书


Victory won''t come to me unless I go to it.