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

时间:2013-11-20 17:28:18

标签: java json 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):致命异常:主要   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):at   android.os.ResultReceiver $ MyRunnable.run(ResultReceiver.java:43)11-20   19:24:55.210:E / AndroidRuntime(5432):at   android.os.Handler.handleCallback(Handler.java:587)11-20   19:24:55.210:E / AndroidRuntime(5432):at   android.os.Handler.dispatchMessage(Handler.java:92)11-20   19:24:55.210:E / AndroidRuntime(5432):at   android.os.Looper.loop(Looper.java:130)11-20 19:24:55.210:   E / AndroidRuntime(5432):at   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 / AndroidRuntime(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 more

P.S。 json响应中的某些项可能会被遗漏。例如

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

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

BTW我无法改变JSON。所以我需要一个解析它的代码。

5 个答案:

答案 0 :(得分:2)

喜欢这个

您的数据

    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);
   }

答案 1 :(得分:1)

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

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;
}

答案 2 :(得分:1)

最近,我出于相同的目的使用了 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

希望帮助

答案 3 :(得分:0)

您发布的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对象。

答案 4 :(得分:0)

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

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

您需要在JsonResponse课程中稍作修改,如下所示

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