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;
    }
相关推荐
腻害兔7 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社8 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
萧瑟余晖9 小时前
JDK 26 新特性详解
java·开发语言
马优晨9 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
维天说12 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane199413 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了13 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品14 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘14 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记14 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端