【问题标题】:GSON Deserialize String or String ArrayGSON 反序列化字符串或字符串数​​组
【发布时间】:2017-10-04 15:42:54
【问题描述】:

我在反序列化包含 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 之外还有许多其他实体我使用相同的方法。但是我不知道如何处理字段值可以是字符串到字符串数组的情况。任何指针将不胜感激。

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    可能最简单的选择是使用自定义序列化器和反序列化器并将value 类型从String 更改为List&lt;String&gt; 以下是解决此问题的基本思路:

    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
    }
    

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

    【讨论】:

    • 谢谢,这很有帮助。几天来我一直在寻找如何做到这一点,我遇到的大多数文章都涉及为整个流程实体编写自定义反序列化程序,我知道必须有更好的方法。
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多