一篇Jackson入门教程奉上

微信扫一扫,分享到朋友圈

一篇Jackson入门教程奉上

前言

现在开发,基本上都离不开JSON格式,也都会涉及到对象与JSON的序列化与反序列化。在Java的世界中,就不得不说fastjson和jackson了,这两个库基本上统治了Java世界中的JSON序列化和反序列化操作。前几天组内评审代码,发现一个项目中既在使用fastjson,又在使用jackson,出现乱用的行为,开发人员也不知道谁是谁,反正就是抓起来用。后来经过评估,统一在项目中使用jackson,同时也总结这篇文章,针对jackson给大家扫盲一下。

Maven依赖

对于非Spring Boot项目,要使用Jackson,则需要添加以下三个依赖:

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


<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.3</version>
</dependency>


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

对于Spring Boot项目,引入了web依赖,就引入了Jackson:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

上面的三个依赖,分别对应Jackson的三个核心模块:


  • Streaming

    :核心包,提供基于”流模式”解析的相关 API,它包括JsonPaser和JsonGenerator。Jackson内部实现正是通过高性能的流模式API的JsonGenerator和JsonParser来生成和解析 json;


  • Annotations

    :注解包,提供标准注解功能;


  • Databind

    :数据绑定包, 提供基于”对象绑定” 解析的相关 API(ObjectMapper )和”树模型” 解析的相关 API(JsonNode);基于”对象绑定” 解析的API和”树模型”解析的API依赖基于”流模式”解析的API。

实战演示

所有的学习都需要落实到实战上面,下面就把我们在实战中常用的Jackson用户进行演示。

下面的演示基于以下几个Bean类,这几个Bean类的结构如下所示:

+-weatherBean类
+--WeatherResultBean类
+-------WeatherSkInfoBean类
+-------WeatherInfoBean类


WeatherBean

类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherBean {
@JsonProperty("resultcode")
private String resultcode;


@JsonProperty("reason")
private String reason;


@JsonProperty("result")
private WeatherResultBean result;


@JsonProperty("error_code")
private int errorCode;


@Override
public String toString() {
return "resultcode:" + this.resultcode + ";reason:" + this.reason +
";error_code:" + this.errorCode;
}


public String getResultcode() {
return resultcode;
}


public void setResultcode(String resultcode) {
this.resultcode = resultcode;
}


public String getReason() {
return reason;
}


public void setReason(String reason) {
this.reason = reason;
}


public WeatherResultBean getResult() {
return result;
}


public void setResult(WeatherResultBean result) {
this.result = result;
}


public int getErrorCode() {
return errorCode;
}


public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
}


WeatherResultBean

类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResultBean {
@JsonProperty("sk")
private WeatherSkInfoBean weatherSkInfoBean;


@JsonProperty("today")
private WeatherInfoBean weatherInfoBean;


public WeatherInfoBean getWeatherInfoBean() {
return weatherInfoBean;
}


public void setWeatherInfoBean(WeatherInfoBean weatherInfoBean) {
this.weatherInfoBean = weatherInfoBean;
}


public WeatherSkInfoBean getWeatherSkInfoBean() {
return weatherSkInfoBean;
}


public void setWeatherSkInfoBean(WeatherSkInfoBean weatherSkInfoBean) {
this.weatherSkInfoBean = weatherSkInfoBean;
}
}


WeatherSkInfoBean

类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherSkInfoBean {
@JsonProperty("temp")
private String temp;


@JsonProperty("wind_direction")
private String windDirection;


@JsonProperty("humidity")
private String humidity;


@JsonProperty("time")
private String time;


public String getTemp() {
return temp;
}


public void setTemp(String temp) {
this.temp = temp;
}


public String getWindDirection() {
return windDirection;
}


public void setWindDirection(String windDirection) {
this.windDirection = windDirection;
}


public String getHumidity() {
return humidity;
}


public void setHumidity(String humidity) {
this.humidity = humidity;
}


public String getTime() {
return time;
}


public void setTime(String time) {
this.time = time;
}
}


WeatherInfoBean

类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherInfoBean {
@JsonProperty("temperature")
private String temperature;


@JsonProperty("weather")
private String weather;


@JsonProperty("weather_id")
private Map<String, String> weatherId;


@JsonProperty("wind")
private String wind;


@JsonProperty("week")
private String week;


@JsonProperty("city")
private String city;


@JsonProperty("date_y")
private String currDate;


@JsonProperty("dressing_index")
private String dressingIndex;


@JsonProperty("dressing_advice")
private String dressingAdvice;


@JsonProperty("uv_index")
private String uvIndex;


@JsonProperty("comfort_index")
private String comfortIndex;


@JsonProperty("wash_index")
private String washIndex;


@JsonProperty("travel_index")
private String travelIndex;


@JsonProperty("exercise_index")
private String exerciseIndex;


@JsonProperty("drying_index")
private String dryingIndex;


// 省略setter和getter代码
}

这是一个相对复杂的结构,我也是把主要贴出来了,争取给大家一个完整的体验。下面就结合我们实际常用的几种场景开始总结。

Bean转JSON

后端开发的接口在给前端返回数据时,都是要求返回JSON串,所以,我们在返回时,都会涉及Bean转JSON的操作,这个在我们的后端开发中肯定会遇到的。

对于上面的结构,我们通过构建Bean类结构,然后调用

ObjectMapper



writeValueAsString

方法即可完成转换。代码如下:

ObjectMapper mapper = new ObjectMapper();
WeatherInfoBean weatherInfoBean = new WeatherInfoBean();
WeatherSkInfoBean weatherSkInfoBean = new WeatherSkInfoBean();
WeatherResultBean weatherResultBean = new WeatherResultBean();
WeatherBean weatherBean = new WeatherBean();


weatherInfoBean.setCity("呼和浩特");
weatherInfoBean.setComfortIndex("");
weatherInfoBean.setCurrDate("2020年11月1日");
weatherInfoBean.setDressingAdvice("建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。");
weatherInfoBean.setDressingIndex("较冷");
weatherInfoBean.setDryingIndex("");
weatherInfoBean.setExerciseIndex("不适宜");
weatherInfoBean.setTemperature("-3℃~10℃");
weatherInfoBean.setTravelIndex("不适宜");
weatherInfoBean.setUvIndex("高等");
weatherInfoBean.setWashIndex("不适宜");
weatherInfoBean.setWeather("晴转阴");


Map<String, String> weatherId = new HashMap<>();
weatherId.put("fa", "00");
weatherId.put("fb", "00");
weatherInfoBean.setWeatherId(weatherId);
weatherInfoBean.setWeek("星期日");
weatherInfoBean.setWind("西北风3-5级");


weatherSkInfoBean.setTemp("2");
weatherSkInfoBean.setWindDirection("西南风");
weatherSkInfoBean.setHumidity("39%");
weatherSkInfoBean.setTime("23:20");


weatherResultBean.setWeatherSkInfoBean(weatherSkInfoBean);
weatherResultBean.setWeatherInfoBean(weatherInfoBean);
weatherBean.setResultcode("200");
weatherBean.setReason("请求成功");
weatherBean.setResult(weatherResultBean);
weatherBean.setErrorCode(0);


String json = mapper.writeValueAsString(weatherBean);
System.out.println(json);

JSON转Bean

在客户端请求后端的接口时,入参基本都是JSON格式的数据,这个时候就需要我们将JSON格式数据转成Bean,以便我们取数据进行对应的处理。现在假设客户端传过来的数据是这样的:

{"resultcode":"200","reason":"successed!","result":{"sk":{"temp":"1","wind_direction":"西北风","wind_strength":"2级","humidity":"38%","time":"23:20"},"today":{"temperature":"-3℃~10℃","weather":"晴","weather_id":{"fa":"00","fb":"00"},"wind":"西北风3-5级","week":"星期六","city":"呼和浩特","date_y":"2020年10月31日","dressing_index":"较冷","dressing_advice":"建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。","uv_index":"中等","comfort_index":"","wash_index":"较适宜","travel_index":"较不宜","exercise_index":"较不宜","drying_index":""}},"error_code":0}

对于Jackson来说,我们只需要以下这样几行代码就可以搞定:

ObjectMapper mapper = new ObjectMapper();
String strJson = "{\"resultcode\":\"200\",\"reason\":\"successed!\"," +
"\"result\":{\"sk\":{\"temp\":\"1\",\"wind_direction\":\"西北风\",\"wind_strength\":\"2级\",\"humidity\":\"38%\",\"time\":\"23:20\"},\"today\":{\"temperature\":\"-3℃~10℃\",\"weather\":\"晴\",\"weather_id\":{\"fa\":\"00\",\"fb\":\"00\"},\"wind\":\"西北风3-5级\",\"week\":\"星期六\",\"city\":\"呼和浩特\",\"date_y\":\"20201031日\",\"dressing_index\":\"较冷\",\"dressing_advice\":\"建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。\",\"uv_index\":\"中等\",\"comfort_index\":\"\",\"wash_index\":\"较适宜\",\"travel_index\":\"较不宜\",\"exercise_index\":\"较不宜\",\"drying_index\":\"\"}},\"error_code\":0}";


Map<String, Object> result = mapper.readValue(strJson, HashMap.class);
WeatherBean weatherBean = mapper.readValue(strJson,
WeatherBean.class);

Map转JSON

上面都是通过Bean来和JSON互转,后来开发不喜欢构建Bean类了,觉的构建Bean类太麻烦,直接通过Map和List来搞定一切,但是在我的团队内部,我是不建议直接使用Map和List来搞定一切的,这样对于后期的运维不是很友好,但是,在一些简单结构的JSON情况下,还是直接使用Map来搞定是比较方便的。

对于上面同样的结构,我们使用Map来实现一下。

Map<String, Object> weatherSkInfoMap = new HashMap<>();
Map<String, Object> weatherInfoMap = new HashMap<>();
Map<String, Object> weatherResultMap = new HashMap<>();
Map<String, Object> weatherMap = new HashMap<>();


weatherSkInfoMap.put("temp", "1");
weatherSkInfoMap.put("wind_direction", "西北风");
weatherSkInfoMap.put("humidity", "39%");
weatherSkInfoMap.put("time", "23:20");


weatherInfoMap.put("temperature", "-3℃~10℃");
weatherInfoMap.put("weather", "晴");
Map<String, String> weatherIdMap = new HashMap<>();
weatherIdMap.put("fa", "00");
weatherIdMap.put("fb", "00");
weatherInfoMap.put("weather_id", weatherIdMap);
weatherInfoMap.put("wind", "西北风3-5级");
weatherInfoMap.put("week", "星期日");
weatherInfoMap.put("city", "呼和浩特");
weatherInfoMap.put("date_y", "2020年11月1日");
weatherInfoMap.put("dressing_index", "较冷");


weatherResultMap.put("sk", weatherSkInfoMap);
weatherResultMap.put("today", weatherInfoMap);


weatherMap.put("resultcode", "200");
weatherMap.put("reason", "请求成功");
weatherMap.put("result", weatherResultMap);
weatherMap.put("error_code", 0);


String json = mapper.writeValueAsString(weatherMap);
System.out.println(json);

JSON转Map

同样,也就存在JSON直接转成Map的情况,也是很简单:

ObjectMapper mapper = new ObjectMapper();
String strJson = "{\"resultcode\":\"200\",\"reason\":\"successed!\"," +
"\"result\":{\"sk\":{\"temp\":\"1\",\"wind_direction\":\"西北风\",\"wind_strength\":\"2级\",\"humidity\":\"38%\",\"time\":\"23:20\"},\"today\":{\"temperature\":\"-3℃~10℃\",\"weather\":\"晴\",\"weather_id\":{\"fa\":\"00\",\"fb\":\"00\"},\"wind\":\"西北风3-5级\",\"week\":\"星期六\",\"city\":\"呼和浩特\",\"date_y\":\"20201031日\",\"dressing_index\":\"较冷\",\"dressing_advice\":\"建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。\",\"uv_index\":\"中等\",\"comfort_index\":\"\",\"wash_index\":\"较适宜\",\"travel_index\":\"较不宜\",\"exercise_index\":\"较不宜\",\"drying_index\":\"\"}},\"error_code\":0}";


MapType javaType =
mapper.getTypeFactory().constructMapType(HashMap.class,
String.class, Object.class);
Map<String, Object> result = mapper.readValue(strJson, javaType);
System.out.println(result.toString());

List转JSON

对于List直接转JSON的情况,和上面的Map方式类似,示例代码如下:

List<String> list = new ArrayList<>();
list.add("呼和浩特");
list.add("深圳");
list.add("大连");
list.add("北京");


String json = mapper.writeValueAsString(list);
System.out.println(json);

JSON转List

对于JSON直接转List的情况,和上面的Map方式类似,示例代码如下:

String json = "[\"呼和浩特\",\"深圳\",\"大连\",\"北京\"]";
CollectionType javaType = mapper.getTypeFactory()
.constructCollectionType(List.class, String.class);
List<String> cityLst = mapper.readValue(json, javaType);
System.out.println(cityLst);

注解说明

在使用Bean的情况下(也是我经常用的情况),我们经常需要配合注解一起使用,这就需要我们对Jackson中的注解有所了解。Jackson中的注解有很多,但是我们常用的也就那么几个,我们最这几个常用的重点注解进行一番总结。


注解

用法


@JsonProperty


用于属性,把属性的名称序列化时转换为另外一个名称


@JsonFormat


用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例:

@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) private Date date;



@JsonAnySetter


用来在序列化和反序列化的时候多余字段可以通过Map来回转换。也就是JSON中的字段比对应的JavaBean中的字段多,可以在JavaBean中使用一个Map字段来接收多余的JSON字段


@JsonAnyGetter


同上


@JsonIgnore


可用于字段、getter/setter、构造函数参数上,作用相同,都会对相应的字段产生影响。使相应字段不参与序列化和反序列化


@JsonIgnoreProperties(ignoreUnknown = true)


该注解是类注解。该注解在Java类和JSON不完全匹配的时候使用。在从JSON反序列化为Java类的时候,

@JsonIgnoreProperties(ignoreUnknown=true)

会忽略所有没有Getter和Setter的属性,也就是忽略类中不存在的字段


@JsonIgnoreProperties({"internalId", "secretKey"})


该注解是类注解。该注解在Java类和JSON不完全匹配的时候使用。在序列化为JSON的时候,

@JsonIgnoreProperties({"internalId", "secretKey"})

会忽略internalId和secretKey两个属性


@JsonRootName


类注解。用于指定JSON根属性的名称


@JsonInclude


用于定义在序列化时是否不应包含某些“非值”(null值或空值)的注解。可以用于每个字段上,也可以用于类上(表示用于类的所有属性)。

@JsonInclude(value = JsonInclude.Include.NON_NULL)

表示忽略类中值为null的字段;

@JsonInclude(Include.NON_EMPTY)

忽略类中值为空的字段,对于字符串,即忽略null或空字符串

总结

希望我的这篇文章对你有帮助。

人生是个圆,有的人走了一辈子也没有走出命运画出的圆圈,其实,圆上的每一个点都有一条腾飞的切线。

玩代码、玩技术

长按识别二维码,关注“果冻想”

如果觉得还不错,可以点个“在看”哦~

微信扫一扫,分享到朋友圈

一篇Jackson入门教程奉上

知识图谱推理的最新研究进展

上一篇

Python高阶函数使用总结!

下一篇

你也可能喜欢

一篇Jackson入门教程奉上

长按储存图像,分享给朋友