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

如何使用Gson实现特殊JSON序列化:展开对象内容而非嵌套

实现Gson嵌套对象展开到JSON根节点的方案

当然可以实现这个需求!你之前尝试的JsonSerializer思路方向没错,但问题在于它只是把UserAddress序列化成一个独立的JsonObject,Gson依然会把这个对象作为userAddress字段的值嵌套在根节点里,而不是直接展开属性。下面给你两种可行的解决方案:


方案一:使用@JsonUnwrapped注解(最简单)

Gson提供了@JsonUnwrapped注解,专门用来实现把嵌套对象的属性直接展开到父对象的JSON层级中,不需要写复杂的序列化逻辑。

步骤1:修改实体类

在User类的userAddress字段上添加@JsonUnwrapped注解:

public class User {
    private int age;
    private String email;
    private boolean isDeveloper;
    private String name;
    
    @JsonUnwrapped // 关键:让Gson展开这个对象的属性
    private UserAddress userAddress;

    // 构造器、getter、setter方法请自行补充
}

public class UserAddress {
    private String city;
    private String country;
    private String houseNumber;
    private String street;

    // 构造器、getter、setter方法请自行补充
}

步骤2:正常序列化

直接使用Gson的默认序列化逻辑即可:

Gson gson = new Gson();
User user = new User(26, "norman@futurestud.io", true, "Norman", 
    new UserAddress("Magdeburg", "Germany", "42A", "Main Street"));
String json = gson.toJson(user);

执行后得到的JSON就是你想要的展开结构,完全没有嵌套的userAddress字段。


方案二:自定义全局User序列化器(灵活处理特殊逻辑)

如果因为版本限制或者需要处理字段冲突、空值等特殊场景,可以自定义序列化整个User对象,手动合并所有属性到根节点。

步骤1:实现自定义序列化器

public class UserSerializer implements JsonSerializer<User> {
    @Override
    public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject rootJson = new JsonObject();
        
        // 添加User自身的属性
        rootJson.addProperty("age", src.getAge());
        rootJson.addProperty("email", src.getEmail());
        rootJson.addProperty("isDeveloper", src.isDeveloper());
        rootJson.addProperty("name", src.getName());
        
        // 合并UserAddress的属性到根节点(先判空避免空指针)
        UserAddress address = src.getUserAddress();
        if (address != null) {
            rootJson.addProperty("city", address.getCity());
            rootJson.addProperty("country", address.getCountry());
            rootJson.addProperty("houseNumber", address.getHouseNumber());
            rootJson.addProperty("street", address.getStreet());
        }
        
        return rootJson;
    }
}

步骤2:注册序列化器并使用

Gson gson = new GsonBuilder()
    .registerTypeAdapter(User.class, new UserSerializer())
    .create();
User user = new User(26, "norman@futurestud.io", true, "Norman", 
    new UserAddress("Magdeburg", "Germany", "42A", "Main Street"));
String json = gson.toJson(user);

这种方式可以完全控制序列化过程,比如遇到User和UserAddress有重名字段时,可以自定义处理规则(比如重命名其中一个字段)。


为什么你之前的代码没成功?

你之前给userAddress字段单独配置的JsonSerializer,只会把UserAddress转换成JsonObject,但Gson依然会把这个JsonObject作为userAddress字段的值添加到根节点中,所以最终还是会保留嵌套结构。只有让序列化器直接操作根节点,或者用@JsonUnwrapped告诉Gson展开属性,才能达到你要的效果。

内容的提问来源于stack exchange,提问作者Stéphane GRILLON

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:12:42