GSON反序列化字符串或字符串数​​组

Aus*_*tin 6 java json gson

我在反序列化包含0到多个子对象的对象时遇到了一些麻烦,这些对象可以包含字符串或特定值的字符串数组.

这是一个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": []
    }]
}
Run Code Online (Sandbox Code Playgroud)

我有一个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;
}
Run Code Online (Sandbox Code Playgroud)

我这样反序列化:

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);
}
Run Code Online (Sandbox Code Playgroud)

我使用动态类型,因为除了Process之外还有许多其他实体,我使用相同的方法.但我无法弄清楚如何处理字段值可以是字符串数组的字符串的情况.任何指针将不胜感激.

var*_*ren 7

可能最简单的选择是使用自定义序列化器和反序列化器并将value类型更改StringList<String>以下基本思路如何解决此问题:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和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
}
Run Code Online (Sandbox Code Playgroud)

PS.如果你可以从Gson切换到Jackson,这个问题可以用1行代码解决DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY