【问题标题】:Using the Gson library to parse unknown data dynamically使用Gson库动态解析未知数据
【发布时间】:2017-08-23 23:55:53
【问题描述】:

我想在 Android Studio 中使用 Gson 库解析以下 JSON 数据。但是数据是通用的..不知道数据中有什么键(对象)..

在学校对象下 - 有数字 1103 是对象。

在那个对象下我们有 shoolname、shortname、students 再次在学生下-有像2201、2202这样的ID ... 这些对象是动态的,不知道有什么反应..

所以问题是如何使用 Gson 在 android 中解析这个 json 字符串?

或任何其他解决方案都是受欢迎的

{
"schools": {
    "home": "1103",
    "statelevel": "1348"
},
"school": {
    "1103": {
        "schoolname": "Indira School",
        "nameshort": "ind",
        "students": {
            "2201": {
                "name": "Ritesh",
                "isCR": true,
                "maths": {
                    "score": 95,
                    "lastscore": 86
                }
            },
            "2202": {
                "name": "Sanket",
                "maths": {
                    "score": 98,
                    "lastscore": 90
                }
            },
            "2203": {
                "name": "Ajit",
                "maths": {
                    "score": 94,
                    "lastscore": 87
                }
            }
        }
    },
    "1348": {
        "schoolname": "Patil School",
        "nameshort": "pat",
        "students": {
            "3201": {
                "name": "Ravi",
                "maths": {
                    "score": 95,
                    "lastscore": 86
                }
            },
            "3202": {
                "name": "Raj",
                "isCR": true,
                "maths": {
                    "score": 98,
                    "lastscore": 90
                }
            },
            "3203": {
                "name": "Ram",
                "maths": {
                    "score": 94,
                    "lastscore": 87
                }
            }
        }
    }
}

}

我参考了How to parse dynamic JSON fields with GSON?.. 但在我的情况下不起作用..我也有内部泛型类。

  1. 我在https://stackoverflow.com/a/23473650/7790252 找到了解决方案。 实现反序列化器以对学校和学生等类进行建模。

【问题讨论】:

  • @oguzhand : 部分重复..在我的情况下,我必须将整个 json 解析到我的 pojo 类中..如果我在 "school:"->{1103...} ..然后它工作了..但是对于内部 json 再次有学生..它没有工作。

标签: json generics gson


【解决方案1】:

您可以简单地使用java.util.Map,它是一个关联键/值容器,其中键和值是任意对象,并且可以使用 Gson 与 JSON 动态对象对齐,非常简单。您只需要定义适当的映射(我将字段折叠起来以节省一些视觉空间):

final class Response {
    @SerializedName("schools") final HomeSchool school = null;
    @SerializedName("school") final Map<Integer, School> schools = null;
}

final class HomeSchool {
    @SerializedName("home") final int home = Integer.valueOf(0);
    @SerializedName("statelevel") final int stateLevel = Integer.valueOf(0);
}

final class School {
    @SerializedName("schoolname") final String name = null;
    @SerializedName("nameshort") final String shortName = null;
    @SerializedName("students") final Map<Integer, Student> students = null;
}

final class Student {
    @SerializedName("name") final String name = null;
    @SerializedName("isCR") final boolean isCr = Boolean.valueOf(false);
    @SerializedName("maths") final Maths maths = null;
}

final class Maths {
    @SerializedName("score") final int score = Integer.valueOf(0);
    @SerializedName("lastscore") final int lastScore = Integer.valueOf(0);
}

现在,一旦你有了映射,你就可以轻松地反序列化你的 JSON:

private static final Gson gson = new Gson();

public static void main(final String... args) {
    final Response response = gson.fromJson(JSON, Response.class);
    for ( final Entry<Integer, School> schoolEntry : response.schools.entrySet() ) {
        final School school = schoolEntry.getValue();
        System.out.println(schoolEntry.getKey() + " " + school.name);
        for ( final Entry<Integer, Student> studentEntry : school.students.entrySet() ) {
            final Student student = studentEntry.getValue();
            System.out.println("\t" + studentEntry.getKey()
                    + " " + student.name
                    + " CR:" + (student.isCr ? "+" : "-")
                    + " (" + student.maths.score + ", " + student.maths.lastScore + ")"
            );
        }
    }
}

1103 英迪拉学校
2201 Ritesh CR:+ (95, 86)
2202 Sanket CR:- (98, 90)
2203 阿吉特 CR:- (94, 87)
1348 帕蒂尔学校
3201 拉维 CR:- (95, 86)
3202 拉吉 CR:+ (98, 90)
3203 公羊 CR:- (94, 87)

类型标记建议部分正确:它们用于反序列化您不能或没有具体映射的对象,例如某物的列表或字符串到某物的映射。在您的情况下,Gson 只需分析字段声明以解析映射类型(键和值)。

【讨论】:

    【解决方案2】:

    来自Gson Documentation

     Type mapType = new TypeToken<Map<Integer, Result> >() {}.getType(); // define generic type
    Map<Integer, Result> result= gson.fromJson(new InputStreamReader(source), mapType);
    

    【讨论】:

    • 如果我使用了部分 Json。即仅在放学后:如果我使用了这个 json "{1103:{...}" 那么它可以工作..但是对于整个 json 它确实有效。
    • 整个 json 意味着内部 json 也必须是通用的,参见 Students
    【解决方案3】:

    创建实现JsonDeserializer的模型对象

    那么你有这个方法可以覆盖:

    @Override
    public ActivityEvents deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        JsonObject jObject = jsonElement.getAsJsonObject();
        for (Map.Entry<String, JsonElement> entry : jObject.entrySet()) {
        entry.getKey(); //here you can get your key 
        gson.fromJson(entry.getValue(), StudebtInfo.class);; //here you can get value for key
        }
    }
    

    【讨论】:

    • 你遇到了什么问题?
    • 我已经为 School、ResultSchool(通用即 1103、1348)、Student、Resulttudents(通用 2201...)..在 resultschool 中创建了反序列化器..在反序列化() ..我应该写什么我dint get..我已经引用了链接..** return new Resultschool(json.getAsJsonPrimitive().getAsString()) ** 但没有工作 -
    猜你喜欢
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 2011-08-13
    • 2018-04-13
    相关资源
    最近更新 更多