如何使用Gson将JSON反序列化为嵌套自定义Map并解决字段为空问题
问题原因
你定义的Match类中存在名为profiles的字段,但你的JSON结构中,match对应的对象下不存在名为profiles的层级,所有动态的username键都是直接挂载在match对象下的。Gson默认按照字段名做属性映射,找不到匹配的profiles字段就会默认赋值为null,且因为Gson对未知字段默认不抛出异常,所以不会有报错提示。
解决方法
下面分两种场景给出方案:
方案1:直接简化数据模型(最推荐,改动最小)
你完全不需要额外定义Match类,直接把外层模型中的match字段定义为Map<String, Profile>即可自动接收所有动态的username键值对:
// 注意类名不要用json,避免和关键字/变量名冲突,首字母大写符合Java规范 class MyJson { private String id; // 直接用Map接收match下所有动态key的键值对 private Map<String, Profile> match; // 可选:添加getter、setter,如果字段为private需要加,或者配置Gson访问权限 public Map<String, Profile> getMatch() { return match; } public void setMatch(Map<String, Profile> match) { this.match = match; } public String getId() { return id; } public void setId(String id) { this.id = id; } } class Profile{ private String id; private String name; // 同样可选添加getter、setter public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
反序列化代码直接使用即可:
Gson gson = new Gson(); var myJson = gson.fromJson(data, MyJson.class); // 访问数据:myJson.getMatch().get("username1") 即可拿到对应的Profile对象
方案2:必须保留Match类结构的场景
如果你因为业务逻辑必须保留Match类的层级结构,可以用两种方式实现:
方式A:让Match继承HashMap
class Match extends HashMap<String, Profile> { // 如有其他额外自定义字段可以在这里添加 } // 外层模型保持原有结构 class MyJson { private String id; private Match match; // getter、setter } class Profile{ private String id; private String name; // getter、setter }
此时Match本身就是Map的实现类,反序列化后可以直接调用match.get("username1")获取数据。
方式B:给Match添加自定义反序列化适配器
如果你不想用继承,必须让Match类内部存在profiles字段存储所有数据,可以为Match类绑定自定义反序列化器:
import com.google.gson.*; import java.lang.reflect.Type; import java.util.Map; // 自定义Match反序列化适配器 class MatchAdapter implements JsonDeserializer<Match> { @Override public Match deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { // 先把match下的所有内容反序列化为Map Type mapType = new com.google.gson.reflect.TypeToken<Map<String, Profile>>(){}.getType(); Map<String, Profile> profiles = context.deserialize(json, mapType); // 组装成Match对象返回 Match match = new Match(); match.setProfiles(profiles); return match; } } // 给Match类绑定适配器 @JsonAdapter(MatchAdapter.class) class Match { private Map<String,Profile> profiles; // getter、setter public Map<String, Profile> getProfiles() { return profiles; } public void setProfiles(Map<String, Profile> profiles) { this.profiles = profiles; } }
注意事项
如果你的类字段声明为private且没有添加getter/setter,需要在构造Gson时配置允许访问私有字段:
Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(java.lang.reflect.Modifier.STATIC, java.lang.reflect.Modifier.FINAL) .create();
内容的提问来源于stack exchange,提问作者slick
相关产品推荐
相关产品推荐

