前言:目前Java开发用到的JSON操作工具有很多,大多都有一点点小问题,我在开发毕设的时候有用过Hutool的JSONUtil、阿里的FastJSON、还有谷歌的GSON。

看过了很多CSDN和各个论坛的文章,感觉对这个JSON顺序问题的解决方案还是比较少相关文章,自己还是做一个记录吧

各个问题

JSONUtil

  • Hutool的JSONUtil在进行JSON转字符串的时候(JSONUtil.toJsonStr()),会有个问题,就是会自动把时间类型LocalDateTime的值转成时间戳,然后存在Redis中,取出来就有问题了,和数据库拿出来的不一样,造成数据不一致

解决方案

  • 序列化配置
  • 用下面的方法(不知道生效不,听说可以)
1
2
3
String mes= JSON.toJSONString(requestMap);
改为
String mes= JSON.toJSONStringWithDateFormat(requestMap,"yyyy-MM-dd HH:mm:ss");

FastJson

  • 阿里的FastJSON更坑,其转换方法会自动给你把JSON数据按key从a—z的顺序排成有序,然后再存入Redis中,再次请求数据顺序就会变了
  • 而且字符串转成JSON的时候也会进行一个key的排序
  • 如果有需要拿到有序的JSON,可以用FastJson这个工具,这个除了顺序变了其他还是挺好的

因为JsonObject 默认空参构造方法是用 HashMap 来存储的,所以输出是按 key 的排序来的

常规解决方案

  • 字符串转JSON的时候,也就是使用JSON.parseObject的时候,要注意赋第二个参数Feature.OrderedField
1
JSONObject data = JSON.parseObject(res , Feature.OrderedField);
  • JSON转字符串的时候,可以用LinkedHashMap来定义要转换的JSONObject
  • 但是我要处理的JSON数据不是自己定义,而是通过Mybatis-Plus内置的分页方法返回的。所以其实也没什么用,上面这个。
  • 具体方案👇
1
2
3
4
5
JSONObject JsonObject = new JSONObject(new LinkedHashMap<>());
// 转换
String JsonString = JsonObject.toJSONString();
// 字符串转JSON,取
JSONObject data = JSON.parseObject(JsonString , Feature.OrderedField);

GSON

  • 相比前面两个,我感觉这个JSON转换工具更好用,没有顺序问题,生态也挺好,就是无法设置null替换,还有时间类型LocalDateTime的转换问题。
  • 默认转换的时候,会把值为null的key给去掉,还有时间类型LocalDateTime也不会做格式化
  • 这里定义一个函数,通过这个函数来进行JSON转换即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.aliveseven.adminmanage.utils;

import com.google.gson.*;

import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateAdapter implements JsonSerializer<LocalDateTime> {
@Override
public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}

public String getJson(Object scr) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.registerTypeAdapter(LocalDateTime.class,new LocalDateAdapter()).create();
return gson.toJson(scr);
}
}