我使用Wikipedia-Api下载以下JSON:
["aa",
["Aarhus","Aalen","Aalborg","Aargau","Aare"],
["","","","",""],
["https://wiki.openstreetmap.org/wiki/Aarhus",
"https://wiki.openstreetmap.org/wiki/Aalen",
"https://wiki.openstreetmap.org/wiki/Aalborg",
"https://wiki.openstreetmap.org/wiki/Aargau",
"https://wiki.openstreetmap.org/wiki/Aare"
]
]
多个在线JSON验证器接受此格式时没有任何警告甚至错误。
我的程序拒绝了这个JSON:
class OsmWikiResult {
private String start;
private String[] file;
private String[] dummy;
private String[] link;
}
... snip ...
Gson gson = new Gson();
OsmWikiResult owr = gson.fromJson(inputLine, OsmWikiResult.class);
inputLine在一行中包含整个JSON。
java -jar target/OsmWiki-1.0-jar-with-dependencies.jar xxxx
OsmWiki
getListFromOsmWiki() starting.
Url: https://wiki.openstreetmap.org/w/api.php?action=opensearch&search=aa&limit=500&namespace=0&format=json
["aa",["Aarhus","Aalen","Aalborg","Aargau","Aare"],["","","","",""],["https://wiki.openstreetmap.org/wiki/Aarhus","https://wiki.openstreetmap.org/wiki/Aalen","https://wiki.openstreetmap.org/wiki/Aalborg","https://wiki.openstreetmap.org/wiki/Aargau","https://wiki.openstreetmap.org/wiki/Aare"]]
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.google.gson.Gson.fromJson(Gson.java:888)
at com.google.gson.Gson.fromJson(Gson.java:853)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at com.wno.OsmWiki.getListFromOsmWiki(OsmWiki.java:80)
at com.wno.OsmWiki.main(OsmWiki.java:114)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
... 6 more
沃尔特
答案 0 :(得分:0)
此处的问题是您尝试使用密钥start
,file
,{dummy
。您需要将根数组解析为link
,然后从中获取单个元素。
以最简单的形式,这样的东西可以起作用:
JsonArray
我建议您创建一个自定义JsonArray root = parser.parse(inputLine).getAsJsonArray();
String searchedTerm = root.get(0).getAsString();
String[] resultTitles = gson.fromJson(root.get(1), String[].class);
String[] dummy = gson.fromJson(root.get(2), String[].class);
String[] links = gson.fromJson(root.get(3), String[].class);
或JsonDeserializer
,以便只能TypeAdapter
整个shebang。由于您的JSON没有非常深的嵌套,我认为您只需实现一个gson.fromJson()
即可。请注意,如果您开始遇到性能问题,可能需要实现JsonDeserializer
。详细了解他们的差异here。
试试这个:
TypeAdapter
注意你需要如何向Gson注册反序列化器,以便它在解析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.JsonParseException;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) {
String inputLine = "[\"aa\",[\"Aarhus\",\"Aalen\",\"Aalborg\",\"Aargau\",\"Aare\"],[\"\",\"\",\"\",\"\",\"\"],[\"https://wiki.openstreetmap.org/wiki/Aarhus\",\"https://wiki.openstreetmap.org/wiki/Aalen\",\"https://wiki.openstreetmap.org/wiki/Aalborg\",\"https://wiki.openstreetmap.org/wiki/Aargau\",\"https://wiki.openstreetmap.org/wiki/Aare\"]]";
Gson gson = new GsonBuilder()
.registerTypeAdapter(OsmWikiResult.class, new WikiSearchResultDeserializer())
.create();
OsmWikiResult result = gson.fromJson(inputLine, OsmWikiResult.class);
System.out.println("result.getSearchTerm() = " + result.getSearchTerm());
System.out.println("result.getResults() = " + String.join(", ", result.getResults()));
System.out.println("result.getLinks() = " + String.join(", ", result.getLinks()));
}
}
class WikiSearchResultDeserializer implements JsonDeserializer<OsmWikiResult> {
@Override
public OsmWikiResult deserialize(
JsonElement json,
Type typeOfT,
JsonDeserializationContext context
) throws JsonParseException {
JsonArray root = json.getAsJsonArray();
String searchTerm = root.get(0).getAsString();
String[] results = context.deserialize(root.get(1), String[].class);
String[] dummy = context.deserialize(root.get(2), String[].class);
String[] links = context.deserialize(root.get(3), String[].class);
return new OsmWikiResult(searchTerm, results, dummy, links);
}
}
class OsmWikiResult {
private String searchTerm;
private String[] results;
private String[] dummy;
private String[] links;
public OsmWikiResult(String searchTerm, String[] results, String[] dummy, String[] links) {
this.searchTerm = searchTerm;
this.results = results;
this.dummy = dummy;
this.links = links;
}
public String getSearchTerm() { return searchTerm; }
public String[] getResults() { return results; }
public String[] getDummy() { return dummy; }
public String[] getLinks() { return links; }
}
时知道该怎么做。解串器只是从API结果的数组中以正确的顺序从阵列元素中提取出来。