1、应用场景:
如果项目中用到json字符串转为jsonObject的需求,并且,需要保证字符串的顺序转之前和转成jsonObject之后输出的结果完全一致。可能有点绕口,下面举一个应用场景的例子。
在做项目的过程中,需要写Junit单元测试,有一个方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@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" )); } |
例子就在这里:
1
|
.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排序。
可以自定义升序或者降序,因为解决不了该场景的问题。这里不赘述,自行百度。
1
|
JSONObject jsonObject = new JSONObject( true ); |
2、解决问题,代码如下,第一个参数是需要转换的json字符串。
1
|
LinkedHashMap<String, Object> jsonMap = JSON.parseObject(facilities,LinkedHashMap. class , Feature.OrderedField); |
1
2
3
4
|
JSONArray jsonArray = new JSONArray(); JSONObject jsonObject = new JSONObject( true ); jsonObject.putAll(jsonMap); jsonArray.add(jsonObject); |
补充:JSON 序列化key排序问题和序列化大小写问题
1. JSON 序列化key排序问题(fastjson)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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.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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//学生类 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//学生类 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的键值对
1
2
3
4
5
6
7
|
//在学生类上加上这个 方式一:(已经过时的方法) 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字段
1
2
|
import com.fasterxml.jackson.databind.DeserializationFeature; MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); |
6. jackson 序列化忽略多余的json字段
1
2
3
4
5
6
|
方式一: @JsonIgnoreProperties :该注解将在类曾级别上使用以忽略json属性。在下面的栗子中,我们将从albums的dataset中忽略“tag”属性; @JsonIgnoreProperties ({ "tags" }) 方式二: @JsonIgnore :该注释将在属性级别上使用以忽略特定属性;get方法上 @JsonIgnore |
7. jackson 常用注解
1
2
3
4
|
@JsonAlias ( "Name" ) 反序列化时生效 private String name; @JsonProperty ( "Name" ) 反序列化和序列化都时生效 private String name; |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。
原文链接:https://blog.csdn.net/weixin_39214304/article/details/80652931