如何使用GSON反序列化不同对象的数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用GSON反序列化不同对象的数组相关的知识,希望对你有一定的参考价值。

我收到这样的JSON

[
  {
    "albums" : [
      {"id":"0", "name":"name"},
      {"id":"1", "name":"name"}
    ],
    "name":"name"
  },
  {
    "tracks" : [
      {"id":"0", "name":"name", "duration":"3:30"},
      {"id":"1", "name":"name", "duration":"2:40"}
    ],
    "name":"name"
  },
  {
    "playlists" : [
      {"id":"0", "name":"name", "tracksCount":"3"},
      {"id":"1", "name":"name", "tracksCount":"40"}
    ],
    "name":"name"
  }
]

当然,我实现了包含所有字段和类的Track,Album和Playlist类

Tracks {
  String name;
  List<Track> tracks;
}
Albums {
  String name;
  List<Album> albums;
}
Playlists {
  String name;
  List<Playlist> playlists;
}

我试图用以下方法对其进行反序列化:

Gson gson = new Gson();
JsonResponse[] rez = gson.fromJson(str, JsonResponse[].class);

JsonResponse在哪里

class JsonResponse {
  Albums albums;
  Tracks tracks;
  Playlists playlists;
}

但我得到错误:

11-20 19:24:55.210:E / androidRuntime(5432):FATAL EXCEPTION:main 11-20 19:24:55.210:E / AndroidRuntime(5432):com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预计BEGIN_OBJECT但是BEGIN_ARRAY在第1行第13栏11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory $ Adapter.read(ReflectiveTypeAdapterFactory.java:176)11 -20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory $ 1.read(ReflectiveTypeAdapterFactory.java:93)11-20 19:24:55.210:E / AndroidRuntime( 5432):at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory $ Adapter.read(ReflectiveTypeAdapterFactory.java:172)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.internal .bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:72) 11-20 19:24:55 210:E / AndroidRuntime(5432):at com.google.gson.Gson.fromJson(Gson.java:803)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.Gson .fromJson(Gson.java:768)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.Gson.fromJson(Gson.java:717)11-20 19:24:55.210 :E / AndroidRuntime(5432):at com.google.gson.Gson.fromJson(Gson.java:689)11-20 19:24:55.210:11-20 19:24:55.210:E / AndroidRuntime(5432):在android.os.ResultReceiver $ MyRunnable.run(ResultReceiver.java:43)11-20 19:24:55.210:E / AndroidRuntime(5432):在android.os.Handler.handleCallback(Handler.java:587)11- 20 19:24:55.210:E / AndroidRuntime(5432):在android.os.Handler.dispatchMessage(Handler.java:92)11-20 19:24:55.210:E / AndroidRuntime(5432):在android.os。 Looper.loop(Looper.java:130)11-20 19:24:55.210:E / AndroidRuntime(5432):在android.app.ActivityThread.main(ActivityThread.java:3687)11-20 19:24:55.210: E / AndroidRuntime(5432):at java.lang.reflect.Method.invokeNative(Native Method)11-20 19:24:55.210:E / And roidRuntime(5432):at java.lang.reflect.Method.invoke(Method.java:507)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller .run(ZygoteInit.java:867)11-20 19:24:55.210:E / AndroidRuntime(5432):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)11-20 19:24 :55.210:E / AndroidRuntime(5432):at dalvik.system.NativeStart.main(Native Method)11-20 19:24:55.210:E / AndroidRuntime(5432):引起:java.lang.IllegalStateException:预期BEGIN_OBJECT但是BEGIN_ARRAY在第1行第13栏11-20 19:24:55.210:E / AndroidRuntime(5432):at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:374)11-20 19:24:55.210 :E / AndroidRuntime(5432):at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory $ Adapter.read(ReflectiveTypeAdapterFactory.java:165)11-20 19:24:55.210:E / AndroidRuntime(5432):...还有21个

附: json响应中的某些项可能会被遗漏。例如

[
  {
    "albums" : [
      {"id":"0", "name":"name"},
      {"id":"1", "name":"name"}
    ],
    "name":"name"
  }
 ]

那么问题是什么?如何反序列化这个JSON?

顺便说一句,我不能改变JSON。所以我需要一个解析它的代码。

答案

这样做

你的数据

    String json = "[{"albums":[{"id":"0","name":"name"},{"id":"1","name":"name"}],"name":"name"},{"tracks":[{"id":"0","name":"name","duration":"3:30"},{"id":"1","name":"name","duration":"2:40"}],"name":"name"},{"playlists":[{"id":"0","name":"name","tracksCount":"3"},{"id":"1","name":"name","tracksCount":"40"}],"name":"name"}]";

你的pojos

class JsonResponse {
      ArrayList<Album> albums;
      ArrayList<Track> tracks;
      ArrayList<Playlist> playlists;
      String name;
    @Override
    public String toString() {
        return "JsonResponse [albums=" + albums + ", tracks=" + tracks
                + ", playlists=" + playlists + ", name=" + name + "]";
    }     
}



class Track{
    int id;
    String name;
    String duration;
    @Override
    public String toString() {
        return "Track [id=" + id + ", name=" + name + ", duration=" + duration
                + "]";
    }    
}

class Album{
    int id;
    String name;
    @Override
    public String toString() {
        return "Album [id=" + id + ", name=" + name + "]";
    }   
}

class Playlist{ 
    int id;
    String name;
    int tracksCount;
    @Override
    public String toString() {
        return "Playlist [id=" + id + ", name=" + name + ", tracksCount="
                + tracksCount + "]";
    }

}

这里是反序列化的数组。

   JsonParser parser = new JsonParser();
   JsonArray Jarray = parser.parse(json).getAsJsonArray();
   Gson gson = new Gson();
   for(JsonElement obj : Jarray )
   {
        JsonResponse jsonResponse = gson.fromJson( obj , JsonResponse.class);
        System.out.println(jsonResponse);
   }
另一答案

谢谢大家的帮助!这是我的解决方案。

public class JsonResponse {
    public static class Item {
        String name;
    }

    public static class Tracks extends Item {
        List<Track> tracks;
    }

    public static class Albums extends Item {
        List<Album> albums;
    }

    public static class Playlists extends Item {
        List<Playlist> playlists;
    }

    public static class JsonResponseDeserialize implements JsonDeserializer<List<? extends Item>> {
        Gson gson = new Gson();
        @Override
        public List<? extends Item> deserialize(JsonElement el, Type type, JsonDeserializationContext context) throws JsonParseException {
            List<Item> ls = new ArrayList<Item>();
            JsonArray jarr = el.getAsJsonArray();
            for (JsonElement e : jarr) {
                Item i;
                if (e.getAsJsonObject().get("tracks") != null){
                    i = gson.lsomJson(e, Tracks.class);
                    if (i != null) {
                        ls.add(i);
                        continue;
                    }
                }
                if (e.getAsJsonObject().get("albums") != null){
                    i = gson.lsomJson(e, Albums.class);
                    if (i != null) {
                        ls.add(i);
                        continue;
                    }
                }
                if (e.getAsJsonObject().get("playlists") != null){
                    i = gson.lsomJson(e, Playlists.class);
                    if (i != null) {
                        ls.add(i);
                        continue;
                    }
                }
            }
            return ls;
        }
    }

    private Tracks _tracks;
    private Albums _albums;
    private Playlists _playlists;
}

反序列化:

private static List<? extends Item> getDatalsomJson(String jsonString) {
    Type type = new TypeToken<List<? extends JsonResponse.Item>>(){}.getType();
    GsonBuilder gb = new GsonBuilder();
    gb.registerTypeAdapter(type, new JsonResponse.JsonResponseDeserialize());
    Gson gson = gb.create();
    List<? extends Item> ls = gson.lsomJson(jsonString, type);
    return ls;
}
另一答案

最近我使用RuntimeTypeAdapterFactory用于相同的目的,它很容易是一个干净的解决方案。这是一个开放的Gson集成(额外)

查看这篇文章以查看和活动示例https://jansipke.nl/serialize-and-deserialize-a-list-of-polymorphic-objects-with-gson/我将原始代码从github直接导入到我的项目中(因为该类不直接拥有maven依赖项):

代码https://raw.githubusercontent.com/google/gson/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java

希望有帮助

另一答案

您发布的JSON不显示JSONResponse对象数组,而是包含“专辑”,“曲目”和“播放列表”类型的JSON对象。如果您有这样的话会有所不同:

[
  {
     {
       "albums" : [
         {"id":"0", "name":"name"},
         {"id":"1", "name":"name"}
       ],
       "name":"name"
     },
     {
       "tracks" : [
         {"id":"0", "name":"name", "duration":"3:30"},
         {"id":"1", "name":"name", "duration":"2:40"}
       ],
       "name":"name"
     },
     {
       "playlists" : [
         {"id":"0", "name":"name", "tracksCount":"3"},
         {"id":"1", "name":"name", "tracksCount":"40"}
       ],
       "name":"name"
     }
   }
]

此外,如果您的对象最终过于复杂,请记住您始终可以实现自己的JSONDeserializer类,并在调用create()之前将其注册到GSONBuilder对象。

另一答案

实际上你在JsonResponse课上犯了错误。

它清晰地形成了你的json格式,它从一个数组开始,而在JsonResponse类中你只是组成单个对象而不是对象的集合。如果你仔细看Gson异常为“BEGIN_OBJECT but was BEGIN_ARRAY”。这意味着Gason的专辑,曲目和播放列表数组不是专辑,曲目和播放列表的对象。

您需要在JsonResponse类中进行一些更改,如下所示

private  List<Albums> albums;
private  List<Tracks> tracks;
private  List<Playlists> playlists;

以上是关于如何使用GSON反序列化不同对象的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 GSON 反序列化 Array 内的 Double 数组?

使用 gson 反序列化反序列化对象的内部对象

完全理解Gson:Gson反序列化

原始类型和数组的 GSON 自定义反序列化器

使用gson,改进将json数组反序列化为模型的正确方法

如何使用 Google 的 Gson API 正确反序列化 JSON?