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

时间:2017-10-04 15:42:54

标签: 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": []
    }]
}

我有一个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之外还有许多其他实体,我使用相同的方法。但我无法弄清楚如何处理字段值可以是字符串数组的字符串的情况。任何指针都会受到赞赏。

1 个答案:

答案 0 :(得分:5)

最简单的选择可能是使用自定义序列化程序和反序列化程序,并将value类型从String更改为List<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;
    }
}

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
}

聚苯乙烯。如果您可以从Gson切换到Jackson,可以使用1行代码DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY

解决此问题