gpt4 book ai didi

android - Gson:反序列化可以是单个对象或数组的对象

转载 作者:行者123 更新时间:2023-11-29 15:39:17 26 4
gpt4 key购买 nike

我正在使用 Gson 解析来自某个 API 的 JSON 响应。一切正常,但现在似乎响应的字段之一可以数组形式或单个元素形式出现,所以我得到 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException :

在这里您可以看到导致问题的两个 JSON 版本的 fragment :

版本 1

{
"Notes": {
"Note": [
{
"key": "disruption-message",
"section": "high",
"priority": "1",
"message": "The battery consumption raised suddenly."
},
{
"key": "disruption-message",
"section": "low",
"priority": "2",
"message": "The power on the converter might be too high."
}
]
}
}

版本 2

{
"Notes": {
"Note": {
"key": "medium",
"section": "low",
"priority": "1",
"message": "Life time for the battery will expire soon"
}
}
}

为了解析VERSION 1,我使用了以下类:

public class Notes implements Serializable {

@SerializedName("Note")
@Expose
private List<Note> note = null;

public List<Note> getNote() {
return note;
}

public void setNote(List<Note> note) {
this.note = note;
}

}

这适用于 VERSION 1 但当它找到与 VERSION 2 匹配的 JSON 响应的一部分时,它当然会给出:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT 

我怎样才能让它反序列化 Notes,无论它们是什么格式?

最佳答案

我猜这个问题属于最著名的 Gson 相关问题组之一,而且设计不当的 JSON 响应会造成伤害。您可以在此处找到准确 解决方案:Make GSON accept single objects where it expects arrays .一旦你有了那个类型的适配器工厂,你就可以像这样注释你的映射:

final class ResponseV1 {

@SerializedName("Notes")
final NotesWrapperV1 notes = null;

}
final class NotesWrapperV1 {

@SerializedName("Note")
@JsonAdapter(AlwaysListTypeAdapterFactory.class)
final List<Note> notes = null;

}
final class Note {

final String key = null;
final String section = null;
final String priority = null;
final String message = null;

}

IMO,您可以更进一步,只需删除内部包装类即可。

final class ResponseV2 {

@SerializedName("Notes")
@JsonAdapter(NestedNotesTypeAdapterFactory.class)
final List<Note> notes = null;

}

NestedNotesTypeAdapterFactory 是这样实现的:

final class NestedNotesTypeAdapterFactory
implements TypeAdapterFactory {

private static final TypeToken<List<Note>> noteListTypeToken = new TypeToken<List<Note>>() {
};

private NestedNotesTypeAdapterFactory() {
}

@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
// Just add the factory method to AlwaysListTypeAdapterFactory and let it just return the class singleton (the factory is stateless, so it can be constructed once)
final TypeAdapter<List<Note>> noteListTypeAdapter = getAlwaysListTypeAdapterFactory().create(gson, noteListTypeToken);
final TypeAdapter<List<Note>> nestedNotesTypeAdapter = new NestedNotesTypeAdapter(noteListTypeAdapter);
@SuppressWarnings("unchecked")
final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) nestedNotesTypeAdapter;
return typeAdapter;
}

private static final class NestedNotesTypeAdapter
extends TypeAdapter<List<Note>> {

private final TypeAdapter<List<Note>> noteListTypeAdapter;

private NestedNotesTypeAdapter(final TypeAdapter<List<Note>> noteListTypeAdapter) {
this.noteListTypeAdapter = noteListTypeAdapter;
}

@Override
public void write(final JsonWriter out, final List<Note> value) {
throw new UnsupportedOperationException();
}

@Override
public List<Note> read(final JsonReader in)
throws IOException {
// "Unwrap" the Note property here
in.beginObject();
List<Note> notes = null;
while ( in.hasNext() ) {
final String name = in.nextName();
switch ( name ) {
case "Note":
// If we've reached the Note property -- just read the list
notes = noteListTypeAdapter.read(in);
break;
default:
throw new MalformedJsonException("Unrecognized " + name + " at " + in);
}
}
in.endObject();
return notes;
}

}
}

两种实现的测试用例:

for ( final String resource : ImmutableList.of("version-1.json", "version-2.json") ) {
System.out.println(resource);
try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43868120.class, resource) ) {
final ResponseV1 response = gson.fromJson(jsonReader, ResponseV1.class);
for ( final Note note : response.notes.notes ) {
System.out.println(note.message);
}
}
}
for ( final String resource : ImmutableList.of("version-1.json", "version-2.json") ) {
System.out.println(resource);
try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43868120.class, resource) ) {
final ResponseV2 response = gson.fromJson(jsonReader, ResponseV2.class);
for ( final Note note : response.notes ) {
System.out.println(note.message);
}
}
}

两者都产生以下结果:

version-1.json
The battery consumption raised suddenly.
The power on the converter might be too high.
version-2.json
Life time for the battery will expire soon

关于android - Gson:反序列化可以是单个对象或数组的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43868120/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com