Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson将JSON对象解析为对象数组_Java_Json_Jackson - Fatal编程技术网

Java Jackson将JSON对象解析为对象数组

Java Jackson将JSON对象解析为对象数组,java,json,jackson,Java,Json,Jackson,我试图在Jackson中解析以下JSON: { "x:y" : 1, "x:z" : 2, "u:v" : 3, // Several dynamically generated entries... } 数据以这种方式格式化,超出了我的控制范围。条目有点动态,但始终采用以下形式: "first:second" : value 我一直在尝试将其序列化到容器类中: private static class MyClass { String first; Stri

我试图在Jackson中解析以下JSON:

{
  "x:y" : 1,
  "x:z" : 2,
  "u:v" : 3,
  // Several dynamically generated entries...
}
数据以这种方式格式化,超出了我的控制范围。条目有点动态,但始终采用以下形式:

"first:second" : value
我一直在尝试将其序列化到容器类中:

private static class MyClass {
    String first;
    String second;
    Number value;

    @JsonCreator
    public MyClass(@JsonProperty("both") String both, @JsonProperty("value") Number value) {
        String[] split = both.split(":");
        first = split[0];
        second = split[1];
        this.value = value;
    }
}
但如果我犯了一个错误:

线程“main”com.fasterxml.jackson.databind.exc.MismatchedInputException中出现异常:无法反序列化项的实例。JacksonObjectTest$MyClass[]超出了START\u对象标记

对我来说有意义;我试图将JSON对象的每个字段解析为一个对象数组,Jackson显然对此不太满意。忽略
@JsonProperty(“两者”)
会产生:

线程“main”com.fasterxml.jackson.databind.exc.InvalidDefinitionException中的异常:类型条目的类型定义无效。JacksonObjectTest$MyClass:参数#0没有属性名,不可注入:无法用作条目的创建者[构造函数。JacksonObjectTest$MyClass,注释:{interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}]

这对我来说也是有意义的;它不知道如何解析这个构造函数(这实际上与上面的问题相同;我放注释只是用另一个错误来掩盖这个错误)

所以我的问题是;如何让杰克逊明白我在这里想要什么

MCVE

public class JacksonObjectTest {
    public static void main(String[] args) throws IOException {
        String data = "{\"x:y\":1,\"x:z\":2,\"u:v\":3}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(data);
        MyClass[] out = mapper.readValue(node.traverse(), MyClass[].class);
        System.out.println(out);
    }

    private static class MyClass {
        String first;
        String second;
        Number value;

        @JsonCreator
        public MyClass(@JsonProperty("both") String both, @JsonProperty("value") Number value) {
            String[] split = both.split(":");
            first = split[0];
            second = split[1];
            this.value = value;
        }
    }
}

EDIT:如评论中所述,我确实知道使用
TypeReference
的方法。这是可行的,但我试图使我的解析代码尽可能包含和通用,使用此解决方案意味着我必须在解析后进行进一步转换,以获得
MyClass[]
(首先解析
映射
,然后处理
MyClass[]
)。有没有办法跳过中间人(即:告诉Jackson如何将已知格式的JSON块处理为数据类型)?

不确定jackson是否可以仅使用内置注释和类解析您的数据结构。当我在解析json时需要添加逻辑时,我总是编写自己的反序列化程序:

public void loadJsonObjectAsArray() throws IOException {
    String data = "{\"x:y\":1,\"x:z\":2,\"u:v\":3}";
    ObjectMapper mapper = new ObjectMapper();
    Wrapper wrapper = mapper.readValue(data, Wrapper.class);
    List<MyClass> out = wrapper.values;
    System.out.println(out);
}

public static class WrapperDeserializer extends StdDeserializer<Wrapper> {
    public WrapperDeserializer() {
        this(null);
    }

    public WrapperDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Wrapper deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        ObjectNode obj = (ObjectNode) node;
        List<MyClass> parsedFields = new ArrayList<>();

        obj.fields().forEachRemaining(fieldAndNode -> {
            String fieldName = fieldAndNode.getKey();
            Number value = fieldAndNode.getValue().numberValue();
            parsedFields.add(new MyClass(fieldName, value));
        });

        return new Wrapper(parsedFields);
    }
}

private static class MyClass {
    String first;
    String second;
    Number value;

    public MyClass(String both, Number value) {
        String[] split = both.split(":");
        first = split[0];
        second = split[1];
        this.value = value;
    }

    @Override
    public String toString() {
        return "MyClass{" +
                "first='" + first + '\'' +
                ", second='" + second + '\'' +
                ", value=" + value +
                '}';
    }
}

@JsonDeserialize(using = WrapperDeserializer.class)
private static class Wrapper {
    private final List<MyClass> values;

    public Wrapper(List<MyClass> values) {
        this.values = new ArrayList<>(values);
    }
}
public void loadJsonObjectAsArray()引发IOException{
字符串数据=“{\'x:y\':1,\'x:z\':2,\'u:v\':3}”;
ObjectMapper mapper=新的ObjectMapper();
Wrapper=mapper.readValue(数据,Wrapper.class);
List out=wrapper.values;
System.out.println(out);
}
公共静态类包装器反序列化器扩展StdDeserializer{
公共包装器反序列化程序(){
这个(空);
}
公共包装器反序列化器(vc类){
超级(vc);
}
@凌驾
公共包装器反序列化(JsonParser jp,反序列化上下文ctxt)引发IOException{
JsonNode节点=jp.getCodec().readTree(jp);
ObjectNode obj=(ObjectNode)节点;
List parsedFields=new ArrayList();
obj.fields().forEachRemaining(fieldAndNode->{
字符串fieldName=fieldAndNode.getKey();
数值=fieldAndNode.getValue().numberValue();
add(新的MyClass(字段名,值));
});
返回新包装(已解析字段);
}
}
私有静态类MyClass{
先串;
弦秒;
数值;
公共MyClass(字符串和数值){
String[]split=both.split(“:”);
第一个=拆分[0];
秒=分裂[1];
这个值=值;
}
@凌驾
公共字符串toString(){
返回“MyClass{”+
“first=”+first+“\”+
,second='+second+'\''+
“,value=“+value+
'}';
}
}
@JsonDeserialize(使用=WrapperDeserializer.class)
私有静态类包装器{
私有最终列表值;
公共包装器(列表值){
this.values=新的ArrayList(值);
}
}

不确定jackson是否可以仅使用内置注释和类解析您的数据结构。当我在解析json时需要添加逻辑时,我总是编写自己的反序列化程序:

public void loadJsonObjectAsArray() throws IOException {
    String data = "{\"x:y\":1,\"x:z\":2,\"u:v\":3}";
    ObjectMapper mapper = new ObjectMapper();
    Wrapper wrapper = mapper.readValue(data, Wrapper.class);
    List<MyClass> out = wrapper.values;
    System.out.println(out);
}

public static class WrapperDeserializer extends StdDeserializer<Wrapper> {
    public WrapperDeserializer() {
        this(null);
    }

    public WrapperDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Wrapper deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        ObjectNode obj = (ObjectNode) node;
        List<MyClass> parsedFields = new ArrayList<>();

        obj.fields().forEachRemaining(fieldAndNode -> {
            String fieldName = fieldAndNode.getKey();
            Number value = fieldAndNode.getValue().numberValue();
            parsedFields.add(new MyClass(fieldName, value));
        });

        return new Wrapper(parsedFields);
    }
}

private static class MyClass {
    String first;
    String second;
    Number value;

    public MyClass(String both, Number value) {
        String[] split = both.split(":");
        first = split[0];
        second = split[1];
        this.value = value;
    }

    @Override
    public String toString() {
        return "MyClass{" +
                "first='" + first + '\'' +
                ", second='" + second + '\'' +
                ", value=" + value +
                '}';
    }
}

@JsonDeserialize(using = WrapperDeserializer.class)
private static class Wrapper {
    private final List<MyClass> values;

    public Wrapper(List<MyClass> values) {
        this.values = new ArrayList<>(values);
    }
}
public void loadJsonObjectAsArray()引发IOException{
字符串数据=“{\'x:y\':1,\'x:z\':2,\'u:v\':3}”;
ObjectMapper mapper=新的ObjectMapper();
Wrapper=mapper.readValue(数据,Wrapper.class);
List out=wrapper.values;
System.out.println(out);
}
公共静态类包装器反序列化器扩展StdDeserializer{
公共包装器反序列化程序(){
这个(空);
}
公共包装器反序列化器(vc类){
超级(vc);
}
@凌驾
公共包装器反序列化(JsonParser jp,反序列化上下文ctxt)引发IOException{
JsonNode节点=jp.getCodec().readTree(jp);
ObjectNode obj=(ObjectNode)节点;
List parsedFields=new ArrayList();
obj.fields().forEachRemaining(fieldAndNode->{
字符串fieldName=fieldAndNode.getKey();
数值=fieldAndNode.getValue().numberValue();
add(新的MyClass(字段名,值));
});
返回新包装(已解析字段);
}
}
私有静态类MyClass{
先串;
弦秒;
数值;
公共MyClass(字符串和数值){
String[]split=both.split(“:”);
第一个=拆分[0];
秒=分裂[1];
这个值=值;
}
@凌驾
公共字符串toString(){
返回“MyClass{”+
“first=”+first+“\”+
,second='+second+'\''+
“,value=“+value+
'}';
}
}
@JsonDeserialize(使用=WrapperDeserializer.class)
私有静态类包装器{
私有最终列表值;
公共包装器(列表值){
this.values=新的ArrayList(值);
}
}

编辑:提供的其他答案能够更好地回答整个问题。将保留此选项,以便为解决方案提供参考
class MultiNamedProperties {

    private List<Property> properties = new ArrayList<>();

    @JsonAnySetter
    public void readProperty(String property, Number value) {
        String[] names = property.split(":");
        properties.add(new Property(names[0], names[1], value));
    }

    @Override
    public String toString() {
        return "MultiNamedProperties{" +
                "properties=" + properties +
                '}';
    }
}

class Property {

    private final String first;
    private final String second;
    private final Number value;

    Property(String first, String second, Number value) {
        this.first = first;
        this.second = second;
        this.value = value;
    }

    @Override
    public String toString() {
        return "MyClass{" +
                "first='" + first + '\'' +
                ", second='" + second + '\'' +
                ", value=" + value +
                '}';
    }
}
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;
import java.util.List;

    public class Main {

        public static void main(String[] args) throws Exception {
            String data = "{\"x:y\":1,\"x:z\":2,\"u:v\":3}";
            ObjectMapper mapper = new ObjectMapper();
            MultiNamedProperties mnp = mapper.readValue(data, MultiNamedProperties.class);
            System.out.println(mnp);
        }
    }
MultiNamedProperties{properties=[MyClass{first='x', second='y', value=1}, MyClass{first='x', second='z', value=2}, MyClass{first='u', second='v', value=3}]}