解決json字符串序列化后的順序問題
1、應(yīng)用場(chǎng)景:
如果項(xiàng)目中用到j(luò)son字符串轉(zhuǎn)為jsonObject的需求,并且,需要保證字符串的順序轉(zhuǎn)之前和轉(zhuǎn)成jsonObject之后輸出的結(jié)果完全一致??赡苡悬c(diǎn)繞口,下面舉一個(gè)應(yīng)用場(chǎng)景的例子。
在做項(xiàng)目的過程中,需要寫Junit單元測(cè)試,有一個(gè)方法如下:
@Test
@SuppressWarnings("unchecked")
public void facilitySoftwareQueryByPageExample() throws Exception {
facilitySoftwareRepository.deleteAll();
FacilitySoftwareConfig facilitySoftware = createFacilitySoftware();
facilitySoftwareRepository.save(facilitySoftware);
String userId = "1";
int pageNumber = 1;
int pageSize = 5;
String facilities = objectMapper.writeValueAsString(facilitySoftware);
LinkedHashMap<String, Object> jsonMap = JSON.parseObject(facilities,LinkedHashMap.class, Feature.OrderedField);
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject(true);
jsonObject.putAll(jsonMap);
jsonArray.add(jsonObject);
this.mockMvc
.perform(get("/v1/facilitysoftware/userid/" + userId + "/page/" + pageNumber
+ "/pagesize/" + pageSize + ""))
.andExpect(status().isOk()).andExpect(jsonPath("content",is(jsonArray)))
.andExpect(jsonPath("totalPages", is(1)))
.andExpect(jsonPath("totalElements", is(1)))
.andExpect(jsonPath("last", is(true)))
.andExpect(jsonPath("number", is(0)))
.andExpect(jsonPath("size", is(5)))
.andExpect(jsonPath("numberOfElements", is(1)))
.andExpect(jsonPath("first", is(true)))
.andDo(document("facilitySoftware-query-example"));
}
例子就在這里:
.andExpect(status().isOk()).andExpect(jsonPath("content",is(jsonArray)))
大家應(yīng)該都能讀懂,這行代碼意思就是你用Api獲取到的json字符串和你定義的字符串是否一致,一致則該條件測(cè)試通過。
這里的比較不僅僅要求所有的key和value都相同,而且需要保證兩個(gè)json串的順序完全相同,才可以完成該條件的測(cè)試。
查了資料解決途徑過程如下:首先我們使用的是阿里的fastJson,需要引入fastJson的依賴,具體百度maven倉庫,注意這里盡量使用穩(wěn)定版本的較高版本。如 1.2.*
在解決問題過程中,遇到如下解決方案
1、在初始化json對(duì)象的時(shí)候加上參數(shù)true,這里不完全符合我們的需求,加上true之后,是讓json串按照key的hashcode排序。
可以自定義升序或者降序,因?yàn)榻鉀Q不了該場(chǎng)景的問題。這里不贅述,自行百度。
JSONObject jsonObject = new JSONObject(true);
2、解決問題,代碼如下,第一個(gè)參數(shù)是需要轉(zhuǎn)換的json字符串。
LinkedHashMap<String, Object> jsonMap = JSON.parseObject(facilities,LinkedHashMap.class, Feature.OrderedField);
JSONArray jsonArray = new JSONArray(); JSONObject jsonObject = new JSONObject(true); jsonObject.putAll(jsonMap); jsonArray.add(jsonObject);
補(bǔ)充:JSON 序列化key排序問題和序列化大小寫問題
1. JSON 序列化key排序問題(fastjson)
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
//創(chuàng)建學(xué)生對(duì)象
Student student = new Student();
student.setName("小明");
student.setSex(1);
student.setAge(18);
//序列化 json key按字典排序
System.out.println(JSONObject.toJSONString(student ,SerializerFeature.MapSortField));
//過濾不要的key age
System.out.println(JSONObject.toJSONString(student , new PropertyFilter() {
public boolean apply(Object source, String name, Object value) {
if ("age".equals(name)) {
return false;
}
return true;
}
}, SerializerFeature.MapSortField));
2. JSON 序列化大小寫問題(fastjson)
//學(xué)生類
import com.alibaba.fastjson.annotation.JSONField;
public class Student {
private String name;
private Integer sex;
private Integer age;
@JSONField(name = "Name") //用于序列化成json,key Name
public String getName() {
return name;
}
@JSONField(name = "Name") 用于json(Name)反序列化成學(xué)生對(duì)象
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
3. jackson 序列化大小寫問題
@ResponseBody和@RequestBody中的序列化和反序列化就是用的jackson
//學(xué)生類
import com.fasterxml.jackson.annotation.JsonProperty;
public class Student {
@JsonProperty("Name")
private String name;
private Integer sex;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//自己測(cè)試下
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
@Test
public void test() throws Exception{
Student student = new Student();
student.setName("小明");
ObjectMapper MAPPER = new ObjectMapper();
//jackson序列化
String json = MAPPER.writeValueAsString(student);
System.out.println(json);
//jackson反序列化
Student student2 = MAPPER.readValue(json, Student.class);
System.out.println(student2.getName());
}
4. jackson 序列化null值的問題
fastjson序列化默認(rèn)會(huì)去掉值為null的鍵值對(duì)
//在學(xué)生類上加上這個(gè) 方式一:(已經(jīng)過時(shí)的方法) import com.fasterxml.jackson.databind.annotation.JsonSerialize; @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 方式二: import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL)
5. jackson 反序列化忽略多余的json字段
import com.fasterxml.jackson.databind.DeserializationFeature; MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
6. jackson 序列化忽略多余的json字段
方式一:
@JsonIgnoreProperties:該注解將在類曾級(jí)別上使用以忽略json屬性。在下面的栗子中,我們將從albums的dataset中忽略“tag”屬性;
@JsonIgnoreProperties({ "tags" })
方式二:
@JsonIgnore:該注釋將在屬性級(jí)別上使用以忽略特定屬性;get方法上
@JsonIgnore
7. jackson 常用注解
@JsonAlias("Name") 反序列化時(shí)生效
private String name;
@JsonProperty("Name") 反序列化和序列化都時(shí)生效
private String name;
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
jxl 導(dǎo)出數(shù)據(jù)到excel的實(shí)例講解
下面小編就為大家分享一篇jxl 導(dǎo)出數(shù)據(jù)到excel的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12
Windows10系統(tǒng)下JDK1.8的下載安裝及環(huán)境變量配置的教程
這篇文章主要介紹了Windows10系統(tǒng)下JDK1.8的下載安裝及環(huán)境變量配置的教程,本文圖文并茂給大家介紹的非常詳細(xì),對(duì)大家的工作或?qū)W習(xí)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
淺談Java中ArrayList的擴(kuò)容機(jī)制
本文主要介紹了淺談Java中ArrayList的擴(kuò)容機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
spring-cloud-gateway動(dòng)態(tài)路由的實(shí)現(xiàn)方法
這篇文章主要介紹了spring-cloud-gateway動(dòng)態(tài)路由的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01

