0

I have a nested json where in the innermost array there are some keys for which the values could either be a string array or an array of array of strings. The json format is not consistent. How do I parse such a json using gson.

I have tried to write a custom de-serializer (see Gson - parsing json with field that is array or string) but that is throwing exception even before I could detect the attribute as string or array and then update the attribute accordingly.

my json is like this

{
"hits" : {
  "total" : 100,
  "max_score" : 1,
  "hits": [
      {"_index": "s1",     
       "_source":{
          "activeOrExpired":[
            ["active"]
          ]
        }
       },
      {"_index": "s1",
       "_source":{
          "activeOrExpired":[
             "expired"
          ]
        }
      }    
    ]
  }
}

My java classes are

public class OuterJson {
    @SerliazedName("hits")
    public Hits hitsOuter;
    public static class Hits {
        public List<InnerHits> innerHits;
    }
}

public InnerHits {
    public String _index;
    public Source _source;
    public static class Source {
        public List<List<String>> activeOrExpired;//I declare this field as                             
                                                 //list of list of strings
        public Source() {
            activeOrExpired = new ArrayList<>();
        }
    }
}

public class CustomDeserializer implements JsonDeserializer<OuterJson> {
    @Override
    public OuterJson deserialize(JsonElement elem, Type type, JsonDeserializationContext context) throws JsonParseException {
        JsonObject outerObj = elem.getAsJsonObject();
        JsonElement innerHits = outerObj.get("hits").getAsJsonObject().get("hits");
        //I want to then detect the type of "activeOrExpired" and convert it         
        //to list of list of strings if it is present just as a string

        //I am getting exception in the below line
        InnerHits[] innerHitsArray = new Gson().fromJson(innerHits, InnerHits[].class);

      //omitting below code for brevity since my code is failing above itself.
    }
}

The exception is

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was String at path $[0]._source.activeOrExpired[0]

Here the innermost "hits" array has the "_source" array which has a field "activeOrExpired" this field is coming either as an array of Strings or array of array of strings. How should I design the custom deserializer to handle such case? I am new to gson and was following the method mentioned in the above link. My code is described above, could anyone please give me some hint on progressing. Thanks!

humblecoder
  • 137
  • 1
  • 7

1 Answers1

0

You can use DSM stream parsing library for such a complex JSON or XML. By using DSM you don't need to create java stub file to deserialize. you can directly deserialize to your own class. It uses YAML based mapping file.

Here is the solution to your question. I am not sure about your object structure. I only deserialize some part of it.

Mapping File:

result:
    type: object  # result is map.
    path: /hits
    fields:
      hits:
        path: hits
        type: array
        fields:
          index:
            path: _index
          source:  
            path: _source/activeOrExpired
            filter: $value!=null
            type: array    # source is also array. 

Use DSM to filter JSON and deserialize.

// you can pass your class to deserialize directly to your class instead of getting  map or list as a result.
//DSM dsm=new DSMBuilder(new File("path/to/maping.yaml")).create(YourClass.class);

DSM dsm=new DSMBuilder(new File("path/to/maping.yaml")).create();
Map<String,Object> hits= (Map<String,Object>)dsm.toObject(new File("path/to/data.json");

json representation of hits variable

{
  "innerHits" : [ {
    "index" : "s1",
    "source" : [ "active" ]
  }, {
    "index" : "s1",
    "source" : [ "expired" ]
  } ]
}
mfe
  • 1,158
  • 10
  • 15
  • Hi Thank you for your answer. Let me go through the DSM resources and would revert back if it solves my task. – humblecoder Mar 31 '19 at 14:41
  • 1
    You are welcome. İf you have any question about DSM I can answer. By the way I am contributor of DSM. – mfe Mar 31 '19 at 15:04