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

如何使用Gson反序列化含动态键的嵌套对象?

如何用Gson解析含动态键名的嵌套JSON?

待解析的示例JSON

[
    {
        "id": "123",
        "a*": {
            "b*": {
                "prio": {
                    "d*": {
                        "id": "234",
                        "name": "test"
                    },
                    "d1*": {
                        "id": "678",
                        "name": "test1"
                    }
                }
            },
            "b1*": {
                "prio": {
                    "d2*": {
                        "id": "234",
                        "name": "test4"
                    }
                },
                "prio": {
                    "d3*": {
                        "id": "234",
                        "name": "test3"
                    }
                }
            }
        },
        "a1*": {
            "b2*": {
                "prio": {
                    "d5*": {
                        "id": "5435",
                        "name": "test2"
                    },
                    "d6*": {
                        "id": "675435438",
                        "name": "test15"
                    }
                }
            }
        }
    },
    {
        "id": "345",
        "f*": {
            "g*": {
                "prio": {
                    "i*": {
                        "id": "5435",
                        "name": "test2"
                    }
                }
            }
        }
    },
    {
        "id": "342343"
    }
]

需求说明

  • 带星号的键为动态变化键名,实际文件中键可能不含星号
  • 嵌套深度不会超过示例,但可能更浅
  • prio的层级固定,需要获取除prio外的所有键名

最初的尝试代码

尝试用实体类映射的方式解析,但firstMap始终为null:

实体类代码

@Getter
@Setter
public class PolicyObject {
    private String id;
    private Map<String, First> firstMap;

    @Getter
    @Setter
    public class First {
        private Map<String, Second> secondMap;
    }

    @Getter
    @Setter
    public class Second {
        private Map<String, Third> prio;
    }

    @Getter
    @Setter
    public class Third {
        private String name;
    }
}

解析逻辑代码

public class mainClass {
    public void main(InputStreamReader file) {
        Type typeOfT = TypeToken.getParameterized(PolicyObject.class, clazz).getType();
        List<PolicyObject> policies = gson.fromJson(file, typeOfT);
    }
}

解决方法:自定义TypeAdapter

通过自定义TypeAdapter处理动态键名的解析,最终解决了问题:

自定义TypeAdapter代码

public class CustomTypeAdapter extends TypeAdapter<PolicyObject> {
    private static final String KEY_ID = "id";
    private static final String KEY_PRIO = "prio";
    private static final String KEY_NAME = "name";

    @Override
    public void write(JsonWriter jsonWriter, PolicyObject policy) throws IOException {

    }

    @Override
    public PolicyObject read(JsonReader reader) throws IOException {
        PolicyObject policyObject = new PolicyObject();
        policyObject.setFirstMap(new HashMap<>());

        reader.beginObject();
        while (reader.hasNext()) {
            String firstName = reader.nextName();
            if (KEY_ID.equals(firstName)) {
                policyObject.setId(reader.nextString());
            } else {
                PolicyObject.First first = new PolicyObject.First();
                first.setSecondMap(new HashMap<>());
                reader.beginObject();
                while (reader.hasNext()) {
                    String secondName = reader.nextName();
                    reader.beginObject();
                    PolicyObject.Second second = new PolicyObject.Second();
                    second.setPrio(new HashMap<>());
                    while (reader.hasNext()) {
                        String prioKey = reader.nextName();
                        if (KEY_PRIO.equals(prioKey)) {
                            reader.beginObject();
                            while (reader.hasNext()) {
                                String thirdName = reader.nextName();
                                reader.beginObject();
                                PolicyObject.Third rule = new PolicyObject.Third();
                                while (reader.hasNext()) {
                                    String ruleProperty = reader.nextName();
                                    if (KEY_NAME.equals(ruleProperty)) {
                                        rule.setName(reader.nextString());
                                    } else {
                                        reader.skipValue();
                                    }
                                }
                                second.getPrio().put(thirdName, rule);
                                reader.endObject();
                            }
                            reader.endObject();
                        } else {
                            reader.skipValue();
                        }
                    }
                    first.getSecondMap().put(secondName, second);
                    reader.endObject();
                }
                reader.endObject();
                policyObject.getFirstMap().put(firstName, first);
            }
        }
        reader.endObject();

        return policyObject;
    }
}

修改后的解析逻辑

public class mainClass {
    public void main(InputStreamReader file) {
        Gson gson = new GsonBuilder().registerTypeAdapter(PolicyObject.class, new CustomTypeAdapter()).create();
        Type typeOfT = new TypeToken<List<PolicyObject>>() {}.getType();
        List<PolicyObject> policies = gson.fromJson(file, typeOfT);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:25:35