【问题标题】:How can I store key-value pairs in JSON to be deserialized in Java?如何在 JSON 中存储键值对以在 Java 中反序列化?
【发布时间】:2016-09-06 00:44:37
【问题描述】:

我有这样的 JSON 数据:

{
    "foo": "bar",
    "key": true,
    "otherKey": 10
}

键是字符串,值是原始类型(int、float、double、long 等)或字符串。我想要一个简单、无强制转换的包装器。

这是我的包装类:

public final class Wrapper<T> {

    private String key;
    private T value;

}

如果我在要反序列化的对象中指定 Wrapper[] wrappedValues,我可以(使用 Jackson 或 GS​​ON)将映射反序列化为包装器列表吗?

感谢您的回复!

【问题讨论】:

    标签: java json jackson gson


    【解决方案1】:

    首先,您指定的输入永远不能反序列化为数组或集合,因为它不是一个。键值对的 json 集合看起来像这样

    [
        {"foo": "bar"},
        {"key": true},
        {"otherKey": 10}
    ] 
    

    如果你像这样创建类,它可以反序列化为Wrappers 的集合

    public class Wrapper<T> {
        private String key;
        private T value;
        @JsonAnySetter
        public void set(String key, Object value) {
            this.key = key;
            this.value = (T)value;
        }
        public String toString() {  // just for nice printing
            return key + "=" + value.toString();
        }
    }
    

    然后你必须告诉 Jackson 将托管反序列化 json 的集合的通用类型是什么:

    public static void main(String[] args)
    {
        String str = "[ {\"foo\": \"bar\"}, {\"key\": true}, {\"otherKey\": 10} ]";
    
        try (InputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"))) {
            ObjectMapper objectMapper = new ObjectMapper();
            JavaType listWrappersType = objectMapper.getTypeFactory()
                    .constructCollectionType(List.class, Wrapper.class);
            List<Wrapper> list = objectMapper.readValue(is, listWrappersType);
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    输出:

    [foo=bar, key=true, otherKey=10]
    

    如果您只想加载键值对而不担心值的类型,那么使用 Jackson 您可以将其全部加载到 Map&lt;String, ?&gt;

        public static void main(String[] args)
        {
            String str = "{ \"foo\": \"bar\", \"key\": true, \"otherKey\": 10 }";
            try (InputStream is = new ByteArrayInputStream(str.getBytes("UTF-8")))  {
                Map<String, ?> map = new ObjectMapper().readValue(is, Map.class);
                // print map contents
                System.out.println(map);
                // print type of map values
                System.out.print(entry.getKey() + "=" + entry.getValue().getClass()+ ", "));
                System.out.println();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    输出

    {foo=bar, key=true, otherKey=10}
    foo=class java.lang.String, key=class java.lang.Boolean, otherKey=class java.lang.Integer,
    

    【讨论】:

    • “数组”是指键:值对的数组(就像你所拥有的那样),但我更喜欢键:值 JSON 而不是 JSON 对象数组,因为它的性质我的项目。所以如果我有这个:{"key":"value", "a":10},我想将它转换为我的包装器的 Java 数组(上图)。它基本上是一个映射,其中的值可以是 JSON 对象以外的任何内容,这就是为什么需要包装器的原因。如果你有一个不涉及的解决方案,我完全赞成。如果这是不可能的,或者我很想尝试,请随时告诉我,我可以使用 JSON 数组系统。
    • 我基本上只想要一个 Map 除了值必须是除 Object 之外的任何 JSON 类型(String、float、long 等)。我创建了包装器以尝试减少强制转换,但如果不可能,我可以调整我的解决方案。
    • 如果你有一个 json 对象列表,每个对象包含未指定数量的 K,V 对,具有未知的键和未知的值类型。你如何解析这样的东西?想象一个对象数组,就像示例中显示的 OP 一样......除了每个对象都有随机数量的 KV 对。
    猜你喜欢
    • 2021-05-01
    • 2014-11-25
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2019-01-01
    • 2016-09-23
    相关资源
    最近更新 更多