JsonPath / Jackson:如何将JSON数组反序列化为单个Object(“[1,2,3]” - > Vector3d实例)? [英] JsonPath/Jackson: how to deserialize JSON array to a single Object ("[1,2,3]" -> Vector3d instance)?

查看:171
本文介绍了JsonPath / Jackson:如何将JSON数组反序列化为单个Object(“[1,2,3]” - > Vector3d实例)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要

我正在使用JsonPath选择部分JSON文件并将其反序列化为POJO。这适用于Strings,但我无法弄清楚如何让Jackson将三元素数组反序列化为我自己的类(Vector3d)的单个实例。 Jackson文档中的所有示例似乎都涉及将JSON中的元素转换为恰好一个Java对象。有什么想法吗?

I'm using JsonPath to select parts of a JSON file and deserialize it into POJOs. This works fine for Strings, but I can't figure out how to get Jackson to deserialize a three-element array as a single instance of my own class (Vector3d). All the examples in the Jackson documentation seem to involve to element in JSON being converted to exactly one Java object. Any ideas?

文档内容

JsonPath文档提到


如果将JsonPath配置为使用JacksonMappingProvider,您甚至可以将JsonPath输出直接映射到POJO中。

If you configure JsonPath to use the JacksonMappingProvider you can even map your JsonPath output directly into POJO's.

Book book = JsonPath.parse(json)。 read($。store.book [0],Book.class);

Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);

但我不能让它工作。

我尝试了什么

我的 Vector3d 类如下所示(注意 @JsonCreator 构造函数):

My Vector3d class looks as follows (note the @JsonCreator constructor):

import com.fasterxml.jackson.annotation.JsonCreator;

public final class Vector3d {
    private final int x, y, z;

    public Vector3d(int x, int y, int z) { 
        this.x = x; this.y = y; this.z = z;
    }

    @JsonCreator
    public Vector3d(int[] values) { 
        this(values[0], values[1], values[2]); 
    }
}

对于这个例子(我使用的实际文件是更复杂):

For this example (the actual file I work with is more complex):

{
    type: "viper",
    location: [
        20,
        173,
        153
    ]
}



<我可以将'location'向量作为一个三元素数组得到如下(这段代码过于冗长,但只是为了保持下一步的小):

I can get the 'location' vector as a three-element array as follows (this code is overly verbose, but just to keep the next step small):

package main;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.internal.JsonReader;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;

import java.util.Arrays;

public class Tester {
    public static void main(String[] args) throws Exception {
        Configuration configuration = Configuration.defaultConfiguration();
        MappingProvider mappingProvider = new JacksonMappingProvider();
        configuration.mappingProvider(mappingProvider);
        JsonReader jsonReader = new JsonReader(configuration);
        DocumentContext documentContext = jsonReader.parse("{\n" +
                "\ttype: \"viper\",\n" +
                "\tlocation: [\n" +
                "\t\t20,\n" +
                "\t\t173,\n" +
                "\t\t153\n" +
                "\t]\n" +
                "}");
        int[] data = documentContext.read("$.location", int[].class);

        System.out.println(Arrays.toString(data));
    }
}

但如果我使用Vector3d而不是int []最后一行,我在read()调用期间得到一个异常:

But if I use Vector3d instead of int[] in the last line, I get an exception during the read() call:

java.lang.RuntimeException: Invalid or non Implemented status createArray() in class net.minidev.json.writer.BeansMapper$Bean
    at net.minidev.json.writer.JsonReaderI.createArray(JsonReaderI.java:98)
    at net.minidev.json.parser.JSONParserBase.readArray(JSONParserBase.java:235)
    at net.minidev.json.parser.JSONParserBase.readFirst(JSONParserBase.java:298)
    at net.minidev.json.parser.JSONParserBase.parse(JSONParserBase.java:154)
    at net.minidev.json.parser.JSONParserString.parse(JSONParserString.java:58)
    at net.minidev.json.parser.JSONParser.parse(JSONParser.java:261)
    at net.minidev.json.JSONValue.parse(JSONValue.java:206)
    at com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider.map(JsonSmartMappingProvider.java:86)
    at com.jayway.jsonpath.internal.JsonReader.convert(JsonReader.java:174)
    at com.jayway.jsonpath.internal.JsonReader.read(JsonReader.java:140)
    at main.Tester.main(Tester.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

我很困惑 Vector3d 构造不起作用,虽然反序列化到 int [] 有效,并添加 @JsonCreator 构造函数 INT [] 。有任何想法吗?

I'm confused that the Vector3d construction doesn't work although deserialization to int[] works, and added @JsonCreator constructor that takes int[]. Any ideas?

推荐答案

不知道内部非静态类是否存在问题。这对我有用:

Don't know if there is an issue with inner non static classes. This works for me:

public class VectorTest {

    private static final String JSON = "{\n" +
            "    \"type\": \"viper\",\n" +
            "    \"location\": [\n" +
            "        20,\n" +
            "        173,\n" +
            "        153\n" +
            "    ]\n" +
            "}";

    static {
        Configuration.setDefaults(new Configuration.Defaults() {
            private final JsonProvider jsonProvider = new JacksonJsonProvider();
            private final MappingProvider mappingProvider = new JacksonMappingProvider();
            private final Set<Option> options = EnumSet.noneOf(Option.class);

            public JsonProvider jsonProvider() {
                return jsonProvider;
            }

            @Override
            public MappingProvider mappingProvider() {
                return mappingProvider;
            }

            @Override
            public Set<Option> options() {
                return options;
            }
        });
    }

    public static final class Vector3d {
        public final int x, y, z;

        @JsonCreator
        public Vector3d(int[] values) {
            this.x = values[0];
            this.y = values[1];
            this.z = values[2];
        }
    }

    @Test
    public void a_test() {
        Vector3d vector = JsonPath.parse(JSON).read("$.location", Vector3d.class);

        Assert.assertThat(vector.x, is(20));
        Assert.assertThat(vector.y, is(173));
        Assert.assertThat(vector.z, is(153));
    }
}

这篇关于JsonPath / Jackson:如何将JSON数组反序列化为单个Object(“[1,2,3]” - &gt; Vector3d实例)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆