23

一篇Jackson入门教程奉上

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzA3MDIyOTAzMA%3D%3D&%3Bmid=2647621875&%3Bidx=1&%3Bsn=2fe31c9db0f46b70a893fd969bd50cb1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

现在开发,基本上都离不开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或空字符串

总结

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

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

yQFzquE.jpg!mobile

玩代码、玩技术

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK