解决json字符串序列化后的顺序问题
1、应⽤场景:
如果项⽬中⽤到json字符串转为jsonObject的需求,并且,需要保证字符串的顺序转之前和转成jsonObject之后输出的结果完全⼀致。可能有点绕⼝,下⾯举⼀个应⽤场景的例⼦。
在做项⽬的过程中,需要写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);
.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)))
⼤家应该都能读懂,这⾏代码意思就是你⽤Api获取到的json字符串和你定义的字符串是否⼀致,⼀致则该条件测试通过。
这⾥的⽐较不仅仅要求所有的key和value都相同,⽽且需要保证两个json串的顺序完全相同,才可以完成该条件的测试。
查了资料解决途径过程如下:⾸先我们使⽤的是阿⾥的fastJson,需要引⼊fastJson的依赖,具体百度maven仓库,注意这⾥尽量使⽤稳定版本的较⾼版本。如 1.2.*
在解决问题过程中,遇到如下解决⽅案
1、在初始化json对象的时候加上参数true,这⾥不完全符合我们的需求,加上true之后,是让json串按照key的hashcode排序。可以⾃定义升序或者降序,因为解决不了该场景的问题。这⾥不赘述,⾃⾏百度。
JSONObject jsonObject = new JSONObject(true);
2、解决问题,代码如下,第⼀个参数是需要转换的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;
//创建学⽣对象
Student student = new Student();
student.setName("⼩明");
student.setSex(1);
student.setAge(18);
//序列化 json key按字典排序
System.out.JSONString(student ,SerializerFeature.MapSortField));
//过滤不要的key age
System.out.JSONString(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;
}
fastjson忽略属性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 = adValue(json, Student.class);
System.out.Name());
}
4. jackson 序列化null值的问题
fastjson序列化默认会去掉值为null的键值对
//在学⽣类上加上这个
⽅式⼀:(已经过时的⽅法)
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;
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;
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。