Tag: Reflection

  • How to get List of Objects from deeper level in Json via GSON

    Sometimes you get a quite nested Json response but the only thing you need is a list of classes in a certain branch of the Json document (like a response of Yahoo’s YQL query).

    Assume just the following json document:

    {
    "fieldA": {
        "fieldB": {
            "fields": [
                { "foo": "test1", "bar": "test2"},
                { "foo": "test11", "bar": "test22"}
             ]
          }
       }
    }
    

    And the only thing you need is the fields array.
    A Java8 way to get the fields as a list would be:

    List<FooBar> quotes2 = Stream.of(gson.fromJson(json, JsonObject.class)
    	.getAsJsonObject("foo")
    	.getAsJsonObject("bar")
    	.getAsJsonArray("foobar"))
    	.flatMap(e -> Stream.of(gson.fromJson(e, FooBar[].class)))
    	.collect(Collectors.toList());
    

    But that’s quite some code. Okay if you only need it once, but as soon as you need this several times it clearly violates the DRY principle. Gson (which I am using a lot) doesn’t seem to provide a simple way for doing this. Except creating the whole hierarchy as Java Classes, which might just be overkill.

    Solving the problem in a more generic way is the way to go – but it als requires creating generic arrays:

    class Gsons{
        public static <T> List<T> asList(String json, String path, Class<T> clazz) {
            Gson gson = new Gson();
            String[] paths = path.split("\\.");
            JsonObject o = gson.fromJson(json, JsonObject.class);
            for (int i = 0; i < paths.length - 1; i++) {
                o = o.getAsJsonObject(paths[i]);
            }
            JsonArray jsonArray = o.getAsJsonArray(paths[paths.length - 1]);
            Class<T[]> clazzArray = (Class<T[]>) ((T[]) Array.newInstance(clazz, 0)).getClass();
            T[] objectArray = gson.fromJson(jsonArray, clazzArray);
            return Arrays.asList(objectArray);
        }
    }
    

    The only things to do are creating a class for the entities and calling the method:

    List<FooBar> fooBars = Gsons.asList(json, "fieldA.fieldB.fields", FooBar.class);