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;
    }
相关推荐
庞轩px4 小时前
第七篇:Spring扩展点——如何优雅地介入Bean的创建流程
java·后端·spring·bean·aware·扩展点
tongluowan0075 小时前
一个请求在Spring MVC 中是怎么流转的
java·spring·mvc
夜郎king6 小时前
Spring AI 对接大模型开发易错点总结与实战解决办法
java·人工智能·spring
oradh6 小时前
Oracle数据库中的Java概述
java·数据库·oracle·sql基础·oracle数据库java概述
组合缺一6 小时前
Java AI 框架三国杀:Solon AI vs Spring AI vs LangChain4j 深度对比
java·人工智能·spring·ai·langchain·llm·solon
c++之路7 小时前
适配器模式(Adapter Pattern)
java·算法·适配器模式
吴声子夜歌7 小时前
Java——接口的细节
java·开发语言·算法
阿拉金alakin7 小时前
深入理解 Java 锁机制:CAS 原理、synchronized 优化与主流锁策略全总结
java·开发语言
myheartgo-on7 小时前
Java—方 法
java·开发语言·算法·青少年编程
雨落在了我的手上7 小时前
如何学习java?
java·开发语言·学习