fastjson与gson的toString差异

背景

这边进行对接外部渠道时,需要对json串进行加签,但是验签一直出错。原因是渠道用了fastjson来处理,我们系统用gson来处理。

例如:

复制代码
String raw = "[{\"z\":1,\"a\":2},{\"b\":1,\"c\":2}]";
// fastJson的toString
System.out.println(JSON.toJSONString(JSON.parse(raw)));
// gson的toString
com.google.gson.JsonParser JSON_PARSER = new com.google.gson.JsonParser();
String raw2 = JSON_PARSER.parse(raw).getAsJsonObject().toString();

fastjson

fastjson的maven依赖

复制代码
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

JSON.toJSONString(Object object);

里真正决定 key 打印顺序 的源码只有一处:

com.alibaba.fastjson.serializer.MapSerializer

write(JSONSerializer serializer, Map map, Object fieldName, Type fieldType, int fieldFeatures)

MapSerializer 是 fastjson 里专门负责"把任何 Map/JSONObject 写成 JSON 字符串"的核心序列化器

一句话:它决定 Map 里的 key-value 最终怎么出现在 JSON 里(顺序、过滤、值序列化、空值处理等)。

复制代码
Map<?, ?> map = (Map)object;
int mapSortFieldMask = SerializerFeature.MapSortField.mask;
if ((out.features & mapSortFieldMask) != 0 || (features & mapSortFieldMask) != 0) {
    if (map instanceof JSONObject) {
        map = ((JSONObject)map).getInnerMap();
    }

    if (!(map instanceof SortedMap) && !(map instanceof LinkedHashMap)) {
        try {
            map = new TreeMap((Map)map); // 关键:TreeMap 按 key 升序
        } catch (Exception var25) {
        }
    }
}
  • 如果传入的 map 是 fastjson 的 JSONObject,就取出它内部真正的 Map,避免重复排序或丢失特性。JSONObject 是 fastjson 提供的一个自定义 Map 实现,它内部包装了一个 Map(通常是 LinkedHashMap),但自身不是 TreeMapLinkedHashMap 的子类。

  • 只要全局或本次调用 带了 MapSortField,就把原 map 包成 TreeMap,后面迭代顺序即字典序。已是 SortedMap/LinkedHashMap 就跳过, 想保留插入序。

gson

Gson#toJson(src) 的 key 顺序只由"原始来源"决定 ,Gson 本身不做任何排序,也不会打乱。

兼容一下:

复制代码
 /**
     * 把 JsonElement 递归转成"按字段名hash"的 JsonElement
     */
    private static JsonElement hashJson(JsonElement el) {
        if (el.isJsonNull() || el.isJsonPrimitive()) {
            return el;                       // 基本类型直接返回
        }
        if (el.isJsonArray()) {
            JsonArray arr = new JsonArray();
            for (JsonElement item : el.getAsJsonArray()) {
                arr.add(hashJson(item));     // 递归处理数组元素
            }
            return arr;
        }
        // JsonObject -> hashMap
        JsonObject obj = el.getAsJsonObject();
        HashMap<String, JsonElement> hashMap = new HashMap<>();
        obj.entrySet().forEach(e -> hashMap.put(e.getKey(), hashJson(e.getValue())));
        JsonObject newObj = new JsonObject();
        hashMap.forEach(newObj::add);
        return newObj;
    }
相关推荐
2601_962071573 小时前
【Java报错已解决】org.springframework.beans.factory.BeanCreationException
java·开发语言
zww89491113 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·eclipse
zww89491116 小时前
匿名树洞系统开发实战:从需求分析到部署指南
java·eclipse
黑马程序员毕设7 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
木井巳7 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
白山编程大哥8 小时前
Java 集合算法:从排序、查找到底层原理的实战指南
java·python·算法
devpotato8 小时前
缓存与数据库更新顺序不一致问题
java·数据库·redis
xcl09258 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·spring boot·需求分析
Kyrie_kk8 小时前
Java--IO--Path文件访问
java·后端
qinqinzqq8 小时前
Maven POM 格式、Schema 与 XSD:一篇讲透
java·maven