SpringBoot学习--06使用jackson返回json数据

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

使用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 : 数据绑定(依赖 coreannotations

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

2.使用

实体类:

//JSON序列化和反序列化使用的User类  
import java.util.Date;  
  
public class User {  
    private String name;  
    private Integer age;  
    private Date birthday;  
    private String email;  
      
    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 getBirthday() {  
        return birthday;  
    }  
    public void setBirthday(Date birthday) {  
        this.birthday = birthday;  
    }  
      
    public String getEmail() {  
        return email;  
    }  
    public void setEmail(String email) {  
        this.email = email;  
    }  
}  

1.序列化

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序列,并把结果输出成字符串。

使用的示例:

import java.io.IOException;  
import java.text.ParseException;  
import java.text.SimpleDateFormat;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class JacksonDemo {  
    public static void main(String[] args) throws ParseException, IOException {  
        User user = new User();  
        user.setName("小民");   
        user.setEmail("xiaomin@sina.com");  
        user.setAge(20);  
          
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");  
        user.setBirthday(dateformat.parse("1996-10-01"));         
          
        ObjectMapper mapper = new ObjectMapper();  
          
        //User类转JSON  
        //输出结果:{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"}  
        String json = mapper.writeValueAsString(user);  
        System.out.println(json);  
          
        //Java集合转JSON  
        //输出结果:[{"name":"小民","age":20,"birthday":844099200000,"email":"xiaomin@sina.com"}]  
        List<User> users = new ArrayList<User>();  
        users.add(user);  
        String jsonlist = mapper.writeValueAsString(users);  
        System.out.println(jsonlist);  
    }  
} 

2.反序列化

import java.io.IOException;  
import java.text.ParseException;  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class JacksonDemo {  
    public static void main(String[] args) throws ParseException, IOException {  
        String json = "{\"name\":\"小民\",\"age\":20,\"birthday\":844099200000,\"email\":\"xiaomin@sina.com\"}";  
          
        /** 
         * ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。 
         */  
        ObjectMapper mapper = new ObjectMapper();  
        User user = mapper.readValue(json, User.class);  
        System.out.println(user);  
    }  
}  

3.JSON注解

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

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

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

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

注:关于日期格式的格式化,jackson提供了两种方法:

1.单独格式化

在对象属性上,或者在属性的 getter 方法上,如下代码所示:
增加到属性上:

/**更新时间 用户可以点击更新,保存最新更新的时间。**/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date updateTime;

增加到 getter 方法上:

@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
public Date getUpdateTime() {
return updateTime;
}

以上结果输出都是一样的。这个没有什么好说明的。具体输出格式,自己调整 pattern 。

@JsonFormat 相差8小时问题
上面直接这么使用,在我们中国来讲和我们的北京时间,会相差8个小时,因为我们是东八区(北京时间)。
所以我们在格式化的时候要指定时区(timezone ),代码如下:

/**更新时间 用户可以点击更新,保存最新更新的时间。**/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;

也就是增加一个属性,timezone="GMT+8" 即可,getter 方法我就不写了,一样的。

2.统一格式化

数据库里面查出来的时间是时间错格式,前端需要处理才能展示相应的格式,自己一个个转的话太麻烦,所以可以在apllication.properties加入下面配置就可以

注意:

前置条件:

image

使用resultMap作为结果返回集

#时间戳统一转换 
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss 
spring.jackson.time-zone=GMT+8

其中time-zone是时区偏移设置,如果不指定的话时间和北京时间会差八个小时。

上述的方法都是针对出参,还有一个日期格式化,不过这个是针对传入的参数,放在Date类型属性或setter方法上,两者可以同时使用,

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;

标签的使用如下:

import java.util.Date;  
import com.fasterxml.jackson.annotation.*;  
  
public class User {  
    private String name;  
      
    //不JSON序列化年龄属性  
    @JsonIgnore   
    private Integer age;  
      
    //格式化日期属性  
    @JsonFormat(pattern = "yyyy年MM月dd日")  
    private Date birthday;  
      
    //序列化email属性为mail  
    @JsonProperty("mail")  
    private String email;  
      
    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 getBirthday() {  
        return birthday;  
    }  
    public void setBirthday(Date birthday) {  
        this.birthday = birthday;  
    }  
      
    public String getEmail() {  
        return email;  
    }  
    public void setEmail(String email) {  
        this.email = email;  
    }  
}  
  
  
  
import java.io.IOException;  
import java.text.ParseException;  
import java.text.SimpleDateFormat;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class JacksonDemo {  
  
    public static void main(String[] args) throws ParseException, IOException {  
        User user = new User();  
        user.setName("小民");   
        user.setEmail("xiaomin@sina.com");  
        user.setAge(20);  
          
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");  
        user.setBirthday(dateformat.parse("1996-10-01"));         
          
        ObjectMapper mapper = new ObjectMapper();  
        String json = mapper.writeValueAsString(user);  
        System.out.println(json);  
        //输出结果:{"name":"小民","birthday":"1996年09月30日","mail":"xiaomin@sina.com"}  
    }  
}  

4.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"); 

原文:https://www.cnblogs.com/zhjh256/p/6049663.html

示例:http://lijingshou.iteye.com/blog/2003112

jackson中各种属性总结:https://www.cnblogs.com/jian-xiao/p/6009435.html?utm_source=itdadao&utm_medium=referral

jackson中的使用方式:https://blog.csdn.net/java_huashan/article/details/46375857

在这里贴上我自己更改后的工具类JsonUtils代码:

package com.luozhen.util.jackson;

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;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容