从经过验证的JSON格式-JavaString解析每个具有多个数组的多个json对象时出现问题 [英] Problem in parsing multiple json objects each having multiple Arrays from a validated JSON format-JavaString

查看:107
本文介绍了从经过验证的JSON格式-JavaString解析每个具有多个数组的多个json对象时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要处理以下JSON字符串(已通过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"
    }]
}
]

示例代码

我能够运行以下示例代码,并能够获得所需的输出.如果我将JSON字符串(即对象"{}"更改为JSON ARRAY"[{},{},{}]")进行解析,并在代码中进行了必要的更改(不知道如何处理数组),那么我会得到在控制台中没有结果.在发现我的错误时感到麻痹.请帮忙.在调整代码方面费了将近一天的时间.

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


}

输出

Name: Mahesh Kumar
Age:21
Verified:false

Marks [ 100 90 85 100 14 95 ]

推荐答案

您的JSON有一个棘手的元素-标签数组包含one-element JSON object.我们可以使用自定义反序列化器对其进行解包.为此,让我们创建适合JSON有效负载的简单POJO结构. JSON[开始,因此这意味着我们需要将其解析为数组.所有元素都具有相同的结构.我们可以如下定义它:

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

JSON中的属性相比,当我们想对Java中的属性使用其他名称时,我们使用SerializedName注释.为了通知Gson库我们希望以特定的方式处理给定的元素,我们使用JsonAdapter批注.如果我们不知道如何编写自定义反序列化器,则对于未知或随机的JSON对象使用Map<String, Object>类型始终是安全的.如果我们有对象列表,则可以使用List<Map<String, Object>>.让我们为标签数组编写简单的反序列化器:

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

算法非常简单:如果给定元素是数组,则对其进行迭代并逐个获取每个对象.对于每个对象,获取所有键并将相应的值添加到labels列表中,这是我们反序列化过程的结果.用法示例如下所示:

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

上面的代码显示:

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

另请参阅:

  • JsonAdapter
  • Serializing and Deserializing a List with Gson

这篇关于从经过验证的JSON格式-JavaString解析每个具有多个数组的多个json对象时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆