java-解析包含多个嵌套对象的JSON对象,而不为每个嵌套对象创建类

java-解析包含多个嵌套对象的JSON对象,而不为每个嵌套对象创建类,第1张

概述我在Android中使用GSON解析JSON对象,该对象的一部分包含多个嵌套对象,这些对象包含所有相同的字段.例如,JSON结构看起来与此类似:{"name":"nestedJSONExample","divisions":{"division1":{"id":str

我在Android中使用GSON解析JsON对象,该对象的一部分包含多个嵌套对象,这些对象包含所有相同的字段.例如,JsON结构看起来与此类似:

        {        "name": "nestedJsONExample",           "divisions": {                "division1": {                  "ID": string                  "name": string,                  "alsoKNownAs": [                    string                  ],                }                "division2": {                  "ID": string                  "name": string,                  "alsoKNownAs": [                    string                  ],                }                 ...                "division99" {                  "ID": string                  "name": string,                  "alsoKNownAs": [                    string                  ],               }            }         }  

在此示例中,所有“ division ##”嵌套对象都包含所有相同的字段,是否可以在不为每个“ division ##”对象创建模型类的情况下将此JsON解析为java类?

即我可以创建如下的Java结构吗?

divisions.division##.ID

不必为每个部门划分班级?

解决方法:

您似乎有些困惑:您不需要为每个division ##节点使用一个映射类,因为无论属性名称如何,您都可以多次重用一个类.关于您喜欢的方式,您可能需要从零到两个自定义映射类:

> 0个自定义映射类(如果自行遍历已解析的JsON对象);
> 1个自定义映射类,如果应用高级解析技术并将映射与类型适配器或JsON对象组合在一起;
> 2个自定义映射类,用于精确映射.

下面的示例使用Java 8语言功能和Java 8 Stream API编写,但是可以轻松地用Java 6重写.下面的JsON常量只是带有以下JsON文档的字符串:

{    "name": "nestedJsONExample",    "divisions": {        "division1": {"ID": "ID1", "name": "name1", "alsoKNownAs": ["alsoKNownAs1A"]},        "division2": {"ID": "ID2", "name": "name2", "alsoKNownAs": ["alsoKNownAs2A"]},        "division3": {"ID": "ID3", "name": "name3", "alsoKNownAs": ["alsoKNownAs3A"]},        "division4": {"ID": "ID4", "name": "name4", "alsoKNownAs": ["alsoKNownAs4A"]},        "division5": {"ID": "ID5", "name": "name5", "alsoKNownAs": ["alsoKNownAs5A"]},        "division6": {"ID": "ID6", "name": "name6", "alsoKNownAs": ["alsoKNownAs6A"]}    }}

没有映射

JsonElement是一个内置的Gson类,表示任何JsON元素.结合JsonElement类及其子类元素,Gson可以构建一个反映给定JsON文档结构的JsON树.因此,仅从根开始遍历就足够了.

final Gson gson = new Gson();final List<String> IDs = gson.fromJson(JsON, JsonElement.class)        .getAsJsonObject()        .get("divisions") // get the divisions property        .getAsJsonObject()        .entrySet() // and traverse its key/value pairs        .stream()        .map(Entry::getValue) // discarding the keys        .map(JsonElement::getAsJsonObject)        .map(jo -> jo.get("ID")) // take the ID property from the every `division` object        .map(JsonElement::getAsJsonPrimitive)        .map(JsonPrimitive::getAsstring)        .collect(toList());System.out.println(IDs);

精确映射

在这里,您可能只需要两个映射类来描述JsON对象之间的关系.除法节点可以只是一个包含任意键和除法值的Map.

final class OuterWithMap {    //String name;    Map<String, division> divisions;}
final class division {    String ID;    //String name;    //List<String> alsoKNownAs;}
final Gson gson = new Gson();final List<String> IDs = gson.fromJson(JsON, OuterWithMap.class)        .divisions        .values() // use map values only ignoring the keys        .stream()        .map(d -> d.ID)        .collect(toList());System.out.println(IDs);

不完全对应

这是最复杂的方法,它显示了使用Gson解析JsON并将给定JsON文档映射到映射类的高级技术可能无法反映真实结构,因此可以即时进行转换.

final class OuterWithList {    //String name;    @JsonAdapter(NoKeysTypeAdapterFactory.class)    List<division> divisions;}
final class NoKeysTypeAdapterFactory        implements TypeAdapterFactory {    // No accessible constructor needed - Gson can instantiate it itself    private NoKeysTypeAdapterFactory() {    }    @OverrIDe    public <T> TypeAdapter<T> create(final Gson gson, final Typetoken<T> typetoken) {        // Is it a List?        if ( List.class.isAssignableFrom(typetoken.getRawType()) ) {            // Try to determine the List element type            final Type elementType = getElementType(typetoken.getType());            // And create a custom type adapter instance bound to the specific List type            @SuppressWarnings("unchecked")            final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) getNoKeysTypeAdapter(gson, elementType);            return typeAdapter;        }        // Otherwise just tell Gson try to find another appropriate parser        return null;    }    private static Type getElementType(final Type type) {        // Is it a generic type with type parameters?        if ( type instanceof ParameterizedType ) {            final ParameterizedType parameterizedType = (ParameterizedType) type;            // If yes, then just take the first type argument since java.util.List can only one type            return parameterizedType.getActualTypeArguments()[0];        }        // Otherwise java.lang.Object due to either Java generics type erasure or raw types usage        return Object.class;    }}
final class NoKeysTypeAdapter<E>        extends TypeAdapter<List<E>> {    private final Gson gson;    private final Type elementType;    private NoKeysTypeAdapter(final Gson gson, final Type elementType) {        this.gson = gson;        this.elementType = elementType;    }    static <E> TypeAdapter<List<E>> getNoKeysTypeAdapter(final Gson gson, final Type elementType) {        return new NoKeysTypeAdapter<>(gson, elementType);    }    @OverrIDe    public voID write(final JsonWriter out, final List<E> value) {        throw new UnsupportedOperationException();    }    @OverrIDe    public List<E> read(final JsonReader in)            throws IOException {        final List<E> List = new ArrayList<>();        // Make sure that the next JsON stream token is `{`        in.beginobject();        // Read until the object ends        while ( in.peek() != END_OBJECT ) {            // Ignore the found JsON object property name            in.nextname();            // And delegate the property value parsing to a downstream parser            final E element = gson.fromJson(in, elementType);            List.add(element);        }        // Make sure that the JsON stream is finished with the `}` token        in.endobject();        return List;    }}

使用特殊的查询库

有一些像JsonPath这样的库可以使JsON文档的查询更加容易. JsonPath可以在没有Gson的情况下工作,但是,据我了解,它使用另一个JsON解析库,并且不解析JsON本身(但我不知道它的实际情况).使用示例:

final JsonPath JsonPath = JsonPath.compile("$.divisions.*.ID");final List<String> IDs = JsonPath.<JsONArray>read(JsON)        .stream()        .map(o -> (String) o)        .collect(toList());System.out.println(IDs);

上面所有四个示例均具有以下输出:

[ID1, ID2, ID3, ID4, ID5, ID6]

总结

以上是内存溢出为你收集整理的java-解析包含多个嵌套对象的JSON对象,而不为每个嵌套对象创建类全部内容,希望文章能够帮你解决java-解析包含多个嵌套对象的JSON对象,而不为每个嵌套对象创建类所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1091341.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存