假设我们有一个像这样的 json,它不能被修改。 我们希望使用 Gson 对其进行反序列化。
{
"user": {
"some_ids": {
"useless_key": [
"22a074ff-91bf-4599-9a9e-374d3f01b6e0",
"66c8ce85-f162-4d92-a836-198a17764efa",
"d0519a9e-bfa2-446c-bb98-746136a3e513"
]
}
}
}
我们想在类 User
中反序列化它,如下所示:
public class User {
@SerializedName("some_ids")
List<String> someIds;
}
问题:
简单的解决方案是创建一个 UselessKey
包装类并将 someIds
列表放入其中。
但是有没有办法告诉 Gson 跳过节点 useless_key
并直接反序列化 someIds
中的列表?
最佳答案
因为你仍然需要标记一个字段应该被不同地处理,Gson 不提供类似的东西。但是你可以实现这样的行为。最接近您要求的是 @JsonAdapter
假设你有
private static final String JSON = "{\n"
+ " \"user\": {\n"
+ " \"some_ids\": {\n"
+ " \"useless_key\": [\n"
+ " \"22a074ff-91bf-4599-9a9e-374d3f01b6e0\",\n"
+ " \"66c8ce85-f162-4d92-a836-198a17764efa\",\n"
+ " \"d0519a9e-bfa2-446c-bb98-746136a3e513\"\n"
+ " ]\n"
+ " }\n"
+ " }\n"
+ "}";
public static void main(final String... args) {
final Gson gson = new Gson();
final Response response = gson.fromJson(JSON, Response.class);
out.println(response.getUser().getSomeIds());
}
DTO Response
类定义如下:
final class Response {
private Response() { }
@SerializedName("user")
private final User user = null;
User getUser() { return user; }
static final class User {
private User() { }
@SerializedName("some_ids")
@JsonAdapter(IdsTypeAdapter.class)
private final List<String> someIds = null;
List<String> getSomeIds() { return someIds; }
}
}
@JsonAdapter(IdsTypeAdapter.class)
中指定的类型适配器上面可以实现如下:
final class IdsTypeAdapter
extends TypeAdapter<List<String>> {
private static final String USELESS_PROPERTY = "useless_key";
private IdsTypeAdapter() {
}
@Override
public void write(final JsonWriter writer, final List<String> value) {
throw new UnsupportedOperationException();
}
@Override
public List<String> read(final JsonReader reader)
throws IOException {
reader.beginObject();
if ( !reader.nextName().equals(USELESS_PROPERTY) ) {
throw new UnsupportedOperationException("Expected: " + USELESS_PROPERTY);
}
reader.beginArray();
final List<String> ids = new ArrayList<>();
while ( reader.peek() == STRING ) {
ids.add(reader.nextString());
}
reader.endArray();
reader.endObject();
return unmodifiableList(ids);
}
}
上面的类型适配器非常简单,并促进流读取以提高性能(@JsonAdapter
注释也需要类型适配器)。结果:
[22a074ff-91bf-4599-9a9e-374d3f01b6e0, 66c8ce85-f162-4d92-a836-198a17764efa, d0519a9e-bfa2-446c-bb98-746136a3e513]
另一种选择是使用 JSON 反序列化器(可以在 GsonBuilder
中注册),但后者会影响性能,因为它们需要在反序列化过程开始之前构建整个 JSON 树。 JSON 反序列化器的另一个问题是 Gson 不支持自定义注释,因此为了标记“特殊”字段,您仍然需要创建一个包装类,如 class StringIds extends ArrayList<String>
。稍后甚至需要反序列化上下文来反序列化给定的 JsonElement
至 List<String>
然后重新映射回 StringIds
.这太贵了。我会选择类型适配器。
关于java - 使用 Gson 反序列化时跳过层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41461421/