我在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对象,而不为每个嵌套对象创建类所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)