You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gson.toJson序列化嵌套org.json.JSONObject时被归入map键问题

解决Gson序列化org.json.JSONObject时的嵌套问题

这个问题我之前也碰到过,核心原因是Gson默认没有内置对org.json.JSONObject的序列化支持,它会把JSONObject当成普通的Map<String, Object>来处理,所以最终序列化出来的结果才会把JSONObject的内容嵌套到map相关的键下。要解决这个,我们需要给Gson添加一个自定义的TypeAdapter,明确告诉它该如何正确处理org.json.JSONObject。

步骤1:编写自定义TypeAdapter

我们需要实现com.google.gson.TypeAdapter<org.json.JSONObject>,重写序列化和反序列化的逻辑:

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import org.json.JSONObject;

import java.io.IOException;

public class JSONObjectTypeAdapter extends TypeAdapter<JSONObject> {
    @Override
    public void write(JsonWriter out, JSONObject value) throws IOException {
        // 直接将JSONObject的字符串写入,Gson会自动解析成正确的JSON结构
        out.jsonValue(value.toString());
    }

    @Override
    public JSONObject read(JsonReader in) throws IOException {
        // 反序列化时,先读取成JsonElement再转成JSONObject
        com.google.gson.JsonElement element = new com.google.gson.JsonParser().parse(in);
        return new JSONObject(element.toString());
    }
}

步骤2:注册适配器到GsonBuilder

在创建Gson实例的时候,把上面的适配器注册进去:

private static final Gson gson = new GsonBuilder()
        .disableHtmlEscaping()
        .registerTypeAdapter(JSONObject.class, new JSONObjectTypeAdapter())
        .create();

完整示例代码

假设你的User类里有一个JSONObject类型的字段,比如:

import org.json.JSONObject;

public class User {
    private String name;
    private int age;
    private JSONObject extraInfo; // 要序列化的JSONObject字段

    // 构造器、getter、setter省略
    public User(String name, int age, JSONObject extraInfo) {
        this.name = name;
        this.age = age;
        this.extraInfo = extraInfo;
    }
}

然后修改你的something方法,用注册了适配器的Gson来序列化:

public class New {
    private static final Gson gson = new GsonBuilder()
            .disableHtmlEscaping()
            .registerTypeAdapter(JSONObject.class, new JSONObjectTypeAdapter())
            .create();

    public static void something(User user) throws Exception {
        // 直接用自定义的Gson实例序列化User对象
        String jsonResult = gson.toJson(user);
        System.out.println(jsonResult);
    }

    public static void main(String[] args) throws Exception {
        JSONObject extra = new JSONObject();
        extra.put("hobby", "reading");
        extra.put("address", "Beijing");
        User user = new User("Alice", 25, extra);
        something(user);
    }
}

效果验证

运行上面的代码,输出的JSON会是这样的:

{"name":"Alice","age":25,"extraInfo":{"hobby":"reading","address":"Beijing"}}

可以看到extraInfo里的内容直接展开了,不会再嵌套到map相关的键下。

额外说明

如果你是先通过Jackson的ObjectMapper把User转成JSON字符串,再转成JSONObject,其实可以跳过这一步,直接用Gson来处理User对象——毕竟混用多个JSON库容易出现兼容性问题,尽量保持序列化/反序列化用同一个库会更稳妥。

内容的提问来源于stack exchange,提问作者Awesumbanana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:01:56