解決json字符串序列化后的順序問題
1、應(yīng)用場景:
如果項目中用到j(luò)son字符串轉(zhuǎn)為jsonObject的需求,并且,需要保證字符串的順序轉(zhuǎn)之前和轉(zhuǎn)成jsonObject之后輸出的結(jié)果完全一致??赡苡悬c繞口,下面舉一個應(yīng)用場景的例子。
在做項目的過程中,需要寫Junit單元測試,有一個方法如下:
@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字符串和你定義的字符串是否一致,一致則該條件測試通過。
這里的比較不僅僅要求所有的key和value都相同,而且需要保證兩個json串的順序完全相同,才可以完成該條件的測試。
查了資料解決途徑過程如下:首先我們使用的是阿里的fastJson,需要引入fastJson的依賴,具體百度maven倉庫,注意這里盡量使用穩(wěn)定版本的較高版本。如 1.2.*
在解決問題過程中,遇到如下解決方案
1、在初始化json對象的時候加上參數(shù)true,這里不完全符合我們的需求,加上true之后,是讓json串按照key的hashcode排序。
可以自定義升序或者降序,因為解決不了該場景的問題。這里不贅述,自行百度。
JSONObject jsonObject = new JSONObject(true);
2、解決問題,代碼如下,第一個參數(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);
補充: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)建學生對象
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)
//學生類
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)反序列化成學生對象
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
//學生類
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;
}
}
//自己測試下
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序列化默認會去掉值為null的鍵值對
//在學生類上加上這個 方式一:(已經(jīng)過時的方法) 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:該注解將在類曾級別上使用以忽略json屬性。在下面的栗子中,我們將從albums的dataset中忽略“tag”屬性;
@JsonIgnoreProperties({ "tags" })
方式二:
@JsonIgnore:該注釋將在屬性級別上使用以忽略特定屬性;get方法上
@JsonIgnore
7. jackson 常用注解
@JsonAlias("Name") 反序列化時生效
private String name;
@JsonProperty("Name") 反序列化和序列化都時生效
private String name;
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Windows10系統(tǒng)下JDK1.8的下載安裝及環(huán)境變量配置的教程
這篇文章主要介紹了Windows10系統(tǒng)下JDK1.8的下載安裝及環(huán)境變量配置的教程,本文圖文并茂給大家介紹的非常詳細,對大家的工作或?qū)W習具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
spring-cloud-gateway動態(tài)路由的實現(xiàn)方法
這篇文章主要介紹了spring-cloud-gateway動態(tài)路由的實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01

