我使用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沃尔特
发布于 2018-04-13 01:08:39
这里的问题是,您试图将一个数组解析为一个具有键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,这样就可以gson.fromJson()整个过程了。由于您的JSON没有很深的嵌套,我认为您可以只实现一个JsonDeserializer。请注意,如果您开始遇到性能问题,您可能希望实现TypeAdapter。阅读更多关于他们不同之处的here。
试试这个:
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; }
}请注意,您需要向Gson注册反序列化程序,以便它知道在解析OsmWikiResult时要做什么。反序列化程序只是按照正确的顺序从API结果的数组中取出数组的元素。
https://stackoverflow.com/questions/49759019
复制相似问题