解决json字符串序列化后的顺序问题
1、应用场景:
如果项目中用到json字符串转为jsonObject的需求,并且,需要保证字符串的顺序转之前和转成jsonObject之后输出的结果完全一致。可能有点绕口,下面举一个应用场景的例子。
在做项目的过程中,需要写Junit单元测试,有一个方法如下:
@Test
@SuppressWarnings("unchecked")
publicvoidfacilitySoftwareQueryByPageExample()throwsException{
facilitySoftwareRepository.deleteAll();
FacilitySoftwareConfigfacilitySoftware=createFacilitySoftware();
facilitySoftwareRepository.save(facilitySoftware);
StringuserId="1";
intpageNumber=1;
intpageSize=5;
Stringfacilities=objectMapper.writeValueAsString(facilitySoftware);
LinkedHashMapjsonMap=JSON.parseObject(facilities,LinkedHashMap.class,Feature.OrderedField);
JSONArrayjsonArray=newJSONArray();
JSONObjectjsonObject=newJSONObject(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)))
大家应该都能读懂,这行代码意思就是你用Api获取到的json字符串和你定义的字符串是否一致,一致则该条件测试通过。
这里的比较不仅仅要求所有的key和value都相同,而且需要保证两个json串的顺序完全相同,才可以完成该条件的测试。
查了资料解决途径过程如下:首先我们使用的是阿里的fastJson,需要引入fastJson的依赖,具体百度maven仓库,注意这里尽量使用稳定版本的较高版本。如1.2.*
在解决问题过程中,遇到如下解决方案
1、在初始化json对象的时候加上参数true,这里不完全符合我们的需求,加上true之后,是让json串按照key的hashcode排序。
可以自定义升序或者降序,因为解决不了该场景的问题。这里不赘述,自行百度。
JSONObjectjsonObject=newJSONObject(true);
2、解决问题,代码如下,第一个参数是需要转换的json字符串。
LinkedHashMapjsonMap=JSON.parseObject(facilities,LinkedHashMap.class,Feature.OrderedField);
JSONArrayjsonArray=newJSONArray(); JSONObjectjsonObject=newJSONObject(true); jsonObject.putAll(jsonMap); jsonArray.add(jsonObject);
补充:JSON序列化key排序问题和序列化大小写问题
1.JSON序列化key排序问题(fastjson)
importcom.alibaba.fastjson.JSONObject;
importcom.alibaba.fastjson.serializer.PropertyFilter;
importcom.alibaba.fastjson.serializer.SerializerFeature;
//创建学生对象
Studentstudent=newStudent();
student.setName("小明");
student.setSex(1);
student.setAge(18);
//序列化jsonkey按字典排序
System.out.println(JSONObject.toJSONString(student,SerializerFeature.MapSortField));
//过滤不要的keyage
System.out.println(JSONObject.toJSONString(student,newPropertyFilter(){
publicbooleanapply(Objectsource,Stringname,Objectvalue){
if("age".equals(name)){
returnfalse;
}
returntrue;
}
},SerializerFeature.MapSortField));
2.JSON序列化大小写问题(fastjson)
//学生类
importcom.alibaba.fastjson.annotation.JSONField;
publicclassStudent{
privateStringname;
privateIntegersex;
privateIntegerage;
@JSONField(name="Name")//用于序列化成json,keyName
publicStringgetName(){
returnname;
}
@JSONField(name="Name")用于json(Name)反序列化成学生对象
publicvoidsetName(Stringname){
this.name=name;
}
publicIntegergetSex(){
returnsex;
}
publicvoidsetSex(Integersex){
this.sex=sex;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
}
3.jackson序列化大小写问题
@ResponseBody和@RequestBody中的序列化和反序列化就是用的jackson
//学生类
importcom.fasterxml.jackson.annotation.JsonProperty;
publicclassStudent{
@JsonProperty("Name")
privateStringname;
privateIntegersex;
privateIntegerage;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicIntegergetSex(){
returnsex;
}
publicvoidsetSex(Integersex){
this.sex=sex;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
}
//自己测试下
importcom.fasterxml.jackson.databind.ObjectMapper;
importorg.junit.Test;
@Test
publicvoidtest()throwsException{
Studentstudent=newStudent();
student.setName("小明");
ObjectMapperMAPPER=newObjectMapper();
//jackson序列化
Stringjson=MAPPER.writeValueAsString(student);
System.out.println(json);
//jackson反序列化
Studentstudent2=MAPPER.readValue(json,Student.class);
System.out.println(student2.getName());
}
4.jackson序列化null值的问题
fastjson序列化默认会去掉值为null的键值对
//在学生类上加上这个 方式一:(已经过时的方法) importcom.fasterxml.jackson.databind.annotation.JsonSerialize; @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 方式二: importcom.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL)
5.jackson反序列化忽略多余的json字段
importcom.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")反序列化时生效
privateStringname;
@JsonProperty("Name")反序列化和序列化都时生效
privateStringname;
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。