Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
355 views
in Technique[技术] by (71.8m points)

java - Problem in parsing multiple json objects each having multiple Arrays from a validated JSON format-JavaString

Want to Process following JSON string (Validated with jsonlint.com)

[{
    "label": "Hospital",
    "domain": "Health_Care",
    "synonymlabels": [{
        "label": "SHCO"
    }, {
        "label": "HCO"
    }],

    "childrenlabels": [{
        "label": "Childern_Hospital"
    }, {
        "label": "Mental_Hospital"
    }, {
        "label": "Heart_Hospital"
    }, {
        "label": "Orthopadic_Hospital"
    }, {
        "label": "General_Hospital"
    }, {
        "label": "Gynac_Hospital"
    }, {
        "label": "Cancer_Hospital"
    }, {
        "label": "Burn_Hospital"
    }, {
        "label": "Trauma_Care_Hospital"
    }]
},

{
    "label": "Doctor",
    "domain": "Health_Care",
    "synonymlabels": [{
        "label": "Clinician"
    }, {
        "label": "Physician"
    }, {
        "label": "Medical_Practitioner"
    }],

    "childrenlabels": [{
        "label": "Cardiaologist"
    }, {
        "label": "Allergist"
    }, {
        "label": "Nurologist"
    }, {
        "label": "Gynacologist"
    }, {
        "label": "General_Physician"
    }, {
        "label": "Anesthetist"
    }, {
        "label": "Physiotherapist"
    }, {
        "label": "Urologist"
    }, {
        "label": "Oncologist"
    }, {
        "label": "Homeopath"
    }, {
        "label": "Dentist"
    }]
}
]

Sample Code

I am able to run the following sample code and able to get the desired output. If I change JSON string i.e. object "{}" to JSON ARRAY "[{},{},{}]" to parse and necessary change in the code (no idea that how to deal with the Array) then I'm getting no results in the console. Feeling paralytic in finding my error. Please help. Struggled for almost a day in tweaking the code.

import java.io.IOException; 
import java.io.StringReader;  

import com.google.gson.stream.JsonReader; 
import com.google.gson.stream.JsonToken;  

public class gsontester { 
   public static void main(String args[]) { 

      String jsonString = 
         "{ "name":"Mahesh Kumar", "age":21,"verified":false,"marks": [100,90,85,100,14,95]}";  
      JsonReader reader = new JsonReader(new StringReader(jsonString));    
      try { 
         handleJsonObject(reader); 
      } 
      catch (IOException e) { 
         e.printStackTrace(); 
      } 
   } 

   private static void handleJsonObject(JsonReader reader) throws IOException { 
      reader.beginObject(); 
      String fieldname = null; 

      while (reader.hasNext()) { 
         JsonToken token = reader.peek(); 

         if (token.equals(JsonToken.BEGIN_ARRAY)) { 
            System.out.print("Marks [ "); 
            handleJsonArray(reader); 
            System.out.print("]"); 
         } else if (token.equals(JsonToken.END_OBJECT)) { 
            reader.endObject(); 
            return; 
         } else {            
            if (token.equals(JsonToken.NAME)) {     
               //get the current token 
               fieldname = reader.nextName(); 
            } 

            if ("name".equals(fieldname)) {       
               //move to next token 
               token = reader.peek(); 
               System.out.println("Name: "+reader.nextString() );           
            } 

            if("age".equals(fieldname)) { 
           //move to next token 
           token = reader.peek(); 
           System.out.println("Age:" + reader.nextInt());       
        } 

        if("verified".equals(fieldname)) { 
           //move to next token 
           token = reader.peek(); 
           System.out.println("Verified:" + reader.nextBoolean());           
        }             
     } 
  } 


}

Output

Name: Mahesh Kumar
Age:21
Verified:false

Marks [ 100 90 85 100 14 95 ]
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your JSON has one tricky element - label arrays contain one-element JSON object. We can unwrap it using custom deserialiser. To do that let's create simple POJO structure which fit's JSON payload. JSON starts from [ so it means we need to parse it as an array. All elements have the same structure. We can define it like below:

class Phrase {

    private String label;
    private String domain;

    @JsonAdapter(StringWrapperJsonDeserializer.class)
    @SerializedName("synonymlabels")
    private List<String> synonymLabels;

    @JsonAdapter(StringWrapperJsonDeserializer.class)
    @SerializedName("childrenlabels")
    private List<String> childrenLabels;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    public List<String> getSynonymLabels() {
        return synonymLabels;
    }

    public void setSynonymLabels(List<String> synonymLabels) {
        this.synonymLabels = synonymLabels;
    }

    public List<String> getChildrenLabels() {
        return childrenLabels;
    }

    public void setChildrenLabels(List<String> childrenLabels) {
        this.childrenLabels = childrenLabels;
    }

    @Override
    public String toString() {
        return "Phrase{" +
                "label='" + label + ''' +
                ", domain='" + domain + ''' +
                ", synonymLabels=" + synonymLabels +
                ", childrenLabels=" + childrenLabels +
                '}';
    }
}

When we want to use another name for property in Java comparing to what we have in JSON we use SerializedName annotation. To inform Gson library that we would like to handle given element in a specific way we use JsonAdapter annotation. In case we do not know how to write custom deserialiser it is always safe to use Map<String, Object> type for unknown or random JSON object. In case we have list of objects we can use List<Map<String, Object>>. Let's write simple deserialiser for labels arrays:

class StringWrapperJsonDeserializer implements JsonDeserializer<List<String>> {

    @Override
    public List<String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (json.isJsonArray()) {
            final JsonArray array = (JsonArray) json;
            final int size = array.size();
            if (size == 0) {
                return Collections.emptyList();
            }

            List<String> labels = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                JsonObject jsonElement = (JsonObject) array.get(i);
                Set<String> keys = jsonElement.keySet();
                for (String key : keys) {
                    labels.add(jsonElement.getAsJsonPrimitive(key).getAsString());
                }
            }

            return labels;
        }

        return Collections.emptyList();
    }
}

Algorithm is quite simple: if given element is an array, iterate over it and take each object one-by-one. For each object get all keys and add corresponding values to labels list which is our result of deserialisation process. Example usage, could look like this:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .create();

        Phrase[] phrases = gson.fromJson(new FileReader(jsonFile), Phrase[].class);
        Stream.of(phrases).forEach(System.out::println);
    }
}

Above code prints:

Phrase{label='Hospital', domain='Health_Care', synonymLabels=[SHCO, HCO], childrenLabels=[Childern_Hospital, Mental_Hospital, Heart_Hospital, Orthopadic_Hospital, General_Hospital, Gynac_Hospital, Cancer_Hospital, Burn_Hospital, Trauma_Care_Hospital]}
Phrase{label='Doctor', domain='Health_Care', synonymLabels=[Clinician, Physician, Medical_Practitioner], childrenLabels=[Cardiaologist, Allergist, Nurologist, Gynacologist, General_Physician, Anesthetist, Physiotherapist, Urologist, Oncologist, Homeopath, Dentist]}

Read also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...