GSON反序列化字符串或字符串数组 [英] GSON Deserialize String or String Array
问题描述
在将包含0的对象反序列化到许多可以包含字符串或特定值的字符串数组的对象时,我遇到了一些麻烦。
例如JSON
{
name:process name,
tasks:[ {
name:task 1,
fields:[{
name:field 1,
value:123abc
$ name b $ b $ value $ b $ name
$ b $ value
$ b $ ]
},
{
name:task 2,
fields:[]
}]
}
我有一个Java实体设置来匹配这样的结构:
public class Process {
public Process(){}
public String name;
public Task []任务;
public class Task {
public Task(){}
public String name;
public Field []字段;
}
public class Field {
public Field()field;
公共字符串名称;
public String value;
}
我反序列化如下:
static< T> T提取(MyHttpRequest请求,Class< T>实体)
{
字符串响应= sendRequestAndParse(请求);
if(response == null){
log.debug(String.format(API response was null%n)));
返回null;
}
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
返回gson.fromJson(response,entity);
$ b我使用动态类型,因为除了Process之外还有其他一些实体,使用相同的方法。但我无法弄清楚如何处理字段值可以是字符串数组的字符串的情况。可能最简单的选择是使用自定义序列化器和反序列化器,并将 value
从字符串到 List< String>
这里有一些基本的想法解决方案:
private static class MyJsonAdapter实现了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>结果;
if(json.isJsonArray()){
result = jsc.deserialize(json,typeOfT);
} else {
result = new ArrayList<>();
result.add((String)jsc.deserialize(json,String.class));
}
返回结果;
$ / code>
和字段POJO
public static class Field {
public String name;
//使用@JsonAdapter(MyJsonAdapter.class)
//或在
中注册序列化器和反序列化器// new GsonBuilder()。registerTypeAdapter(new MyJsonAdapter())
@JsonAdapter(MyJsonAdapter.class)
public List< String>值; //需要将值类型更改为列表
}
如果您可以从Gson切换到Jackson,则可以使用1行代码反序列化功能.ACCEPT_SINGLE_VALUE_AS_ARRAY 来解决此问题。
I've had some trouble deserializing an object that contains 0 to many child objects that can either contains a string or a string array for a particular value.
Here's an example 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": []
}]
}
I have a Java entity setup to match this structure like this:
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;
}
And I deserialize like such:
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);
}
I use dynamic types because there's a number of other entities other than Process that I use this same method for. But I can't figure out how to handle the case where the field value can be either a string to an array of string. Any pointers would be appreciated.
解决方案 Probably the most simple option is to use custom serializer and deserializer and change value
type from String
to List<String>
Here is basic idea how you can solve this:
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;
}
}
And Field 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. If you could switch to Jackson from Gson, this problem could be solved with 1 line of code DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
这篇关于GSON反序列化字符串或字符串数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!