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;
    }
相关推荐
Rabitebla13 小时前
C++类和对象(中):默认函数 + 运算符重载 + 日期类实现完整笔记
java·开发语言·javascript
Bat U14 小时前
JavaEE|多线程(一)
java·服务器·开发语言
逻辑驱动的ken14 小时前
Java高频面试考点场景题05
java·开发语言·深度学习·求职招聘·春招
SamDeepThinking14 小时前
秒杀系统需求PRD
java·后端·架构
一 乐14 小时前
咖啡商城|基于springboot + vue咖啡商城系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·咖啡商城系统
Royzst14 小时前
String方法
java·开发语言
学习使我健康14 小时前
Android 事件分发机制
android·java·前端
20YC编程社区14 小时前
一分钟了解JSON格式,使用场景,和它的优缺点
json
瀚高PG实验室14 小时前
因磁盘IO性能低导致程序An I/O error 报错
java·jvm·数据库·瀚高数据库
好家伙VCC14 小时前
**发散创新:基于FFmpeg的视频编码优化实践与实战代码解析**在现代多媒体系统中,
java·python·ffmpeg·音视频