解决json字符串序列化后的顺序问题

 更新时间:2021年03月15日 14:15:17   作者:peng-peng-  
这篇文章主要介绍了解决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);
  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排序。

可以自定义升序或者降序,因为解决不了该场景的问题。这里不赘述,自行百度。

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.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的键值对

//在学生类上加上这个
方式一:(已经过时的方法)
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;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

  • idea创建项目没有webapp文件夹的解决方法

    idea创建项目没有webapp文件夹的解决方法

    本文主要介绍了idea创建项目没有webapp文件夹的解决方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Spring Boot 校验用户上传的图片文件(两种方式)

    Spring Boot 校验用户上传的图片文件(两种方式)

    图片上传是现代应用中非常常见的一种功能,也是风险比较高的一个地方,恶意用户可能会上传一些病毒、木马,本文给大家介绍两种对图片文件进行校验的方法,感兴趣的朋友一起看看吧
    2023-11-11
  • Java反射机制的实现详解

    Java反射机制的实现详解

    反射主要解决动态编程,即使用反射时,所有的对象生成是动态的,因此调用的方法也是动态的.反射可以简化开发,但是代码的可读性很低
    2013-05-05
  • 详解Spring Bean的循环依赖解决方案

    详解Spring Bean的循环依赖解决方案

    这篇文章主要介绍了详解Spring Bean的循环依赖解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • IDEA远程管理docker镜像及容器服务的实现

    IDEA远程管理docker镜像及容器服务的实现

    本文主要介绍了IDEA远程管理docker镜像及容器服务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Mybatis plus实现Distinct去重功能

    Mybatis plus实现Distinct去重功能

    这篇文章主要介绍了Mybatis plus实现Distinct去重功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 使用ServletInputStream在拦截器或过滤器中应用后重写

    使用ServletInputStream在拦截器或过滤器中应用后重写

    这篇文章主要介绍了使用ServletInputStream在拦截器或过滤器中应用后重写,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • JAVA获取特定格式时间方式

    JAVA获取特定格式时间方式

    我们有时要获取时间,年月日时分秒周几,有时要以特定的格式出现,本文主要介绍了JAVA获取特定格式时间方式,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • 一篇文章带你玩转Spring bean的终极利器

    一篇文章带你玩转Spring bean的终极利器

    这篇文章主要给大家介绍了关于玩转Spring bean的终极利器的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring bean具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • linux下idea、pycharm等输入中文拼音时满3个字母后无法继续拼音输入的问题

    linux下idea、pycharm等输入中文拼音时满3个字母后无法继续拼音输入的问题

    这篇文章主要介绍了linux下idea、pycharm等输入中文拼音时满3个字母后无法继续拼音输入的问题,本文通过图文并茂的形式给大家分享解决方法,需要的朋友可以参考下
    2021-04-04

最新评论