java - 解析多个 json 对象时出现问题,每个对象都有来自经过验证的 JSON 格式的多个数组-JavaString
问题描述
想要处理以下 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 "[{},{},{}]" 以解析并在代码中进行必要的更改(不知道如何处理数组),那么我得到了控制台中没有结果。在发现我的错误时感到麻痹。请帮忙。在调整代码方面挣扎了将近一天。
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
. 我们可以使用自定义反序列化器解开它。为此,让我们创建POJO
适合有效负载的简单结构JSON
。JSON
从[
所以这意味着我们需要将它解析为一个数组。所有元素都具有相同的结构。我们可以像下面这样定义它:
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 +
'}';
}
}
当我们想使用另一个名称来Java
比较我们使用的属性时,JSON
我们使用SerializedName
注释。为了通知Gson
库我们希望以特定方式处理给定元素,我们使用JsonAdapter
注释。如果我们不知道如何编写自定义反序列化器,Map<String, Object>
对未知或随机JSON
对象使用类型总是安全的。如果我们有可以使用的对象列表List<Map<String, Object>>
。让我们为标签数组编写简单的反序列化器:
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
列表中,这是我们反序列化过程的结果。示例用法,可能如下所示:
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]}
另请阅读:
推荐阅读
- javascript - Jquery 缩放插件不瞄准和缩放
- scala - 无形中HList结构的证明
- c# - IE Windows 安全对话框出现阻止 Selenium 导航
- php - PhpSpreadsheet:权限 | ZipArchive::close(): 创建临时文件失败
- qt - 从 Qt 项目构建 .deb
- java - 为什么我进行堆转储后内存会下降?
- swift - 为 tableview 部分构建 Firebase 模型
- javascript - 为什么单击按钮时无法获得警报
- openshift - OpenShift Origin - 从 Web 控制台添加节点
- c# - 如果设置了 Min Pool Size,池中连接的生命周期是多少?