GSON反序列化字符串或字符串数组
问题描述:
我有一些麻烦反序列化包含0的对象到许多可以包含特定值的字符串或字符串数组的子对象。GSON反序列化字符串或字符串数组
下面是一个例子JSON
{
"name": "process name",
"tasks": [{
"name": "task 1",
"fields": [{
"name": "field 1",
"value": "123abc"
},
{
"name": "field 2",
"value": ["value 1", "value 2"]
}
]
},
{
"name": "task 2",
"fields": []
}]
}
我有一个Java实体设置来匹配这个结构是这样的:
public class Process {
public Process() {}
public String name;
public Task[] tasks;
}
public class Task {
public Task() {}
public String name;
public Field[] fields;
}
public class Field {
public Field() field;
public String name;
public String value;
}
我反序列化像这样:
static <T> T fetch(MyHttpRequest request, Class<T> entity)
{
String response = sendRequestAndParse(request);
if (response == null) {
log.debug(String.format("API response was null %n)"));
return null;
}
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
return gson.fromJson(response, entity);
}
我用动态类型,因为除了Process以外,还有一些其他实体我使用了相同的方法。但我无法弄清楚如何处理字段值可以是字符串数组的字符串的情况。任何指针将不胜感激。
答
可能是最简单的选择是使用自定义的串行器和解串并改变从String
到List<String>
value
型这是基本的想法,你如何解决这个问题:
private static class MyJsonAdapter implements JsonSerializer<List<String>>,
JsonDeserializer<List<String>>{
@Override
public JsonElement serialize(List<String> list, Type t,
JsonSerializationContext jsc) {
if (list.size() == 1) {
return jsc.serialize(list.get(0));
} else {
return jsc.serialize(list);
}
}
@Override
public List<String> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext jsc)
throws JsonParseException {
List<String> result;
if (json.isJsonArray()) {
result = jsc.deserialize(json, typeOfT);
}else {
result = new ArrayList<>();
result.add((String) jsc.deserialize(json, String.class));
}
return result;
}
}
田径POJO
public static class Field {
public String name;
// Use @JsonAdapter(MyJsonAdapter.class)
// or register serializer and deserializer in
// new GsonBuilder().registerTypeAdapter(new MyJsonAdapter())
@JsonAdapter(MyJsonAdapter.class)
public List<String> value; // need to change value type to list
}
Ps。如果你可以从Gson切换到Jackson,这个问题可以用1行代码来解决。DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
谢谢你,这是非常有帮助的。我一直在寻找如何做到这一点几天,我遇到的大多数文章都涉及到为整个流程实体编写自定义反序列化器,我知道必须有更好的方法。 – Austin