Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.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反序列化要列出的重复密钥_Java_Json_Spring Boot_Jackson - Fatal编程技术网

Java 使用Jackson反序列化要列出的重复密钥

Java 使用Jackson反序列化要列出的重复密钥,java,json,spring-boot,jackson,Java,Json,Spring Boot,Jackson,我正在尝试将json反序列化为对象。但是,json有重复的键。我无法更改json,我想使用Jackson将重复键更改为列表 以下是我检索的json示例: { "myObject": { "foo": "bar1", "foo": "bar2" } } 下面是我在反序列化之后想要的: { "myObject": { "foo": ["bar1","bar2"] } } 我是这样创建我的类的: public class MyObject { pri

我正在尝试将json反序列化为对象。但是,json有重复的键。我无法更改json,我想使用Jackson将重复键更改为列表

以下是我检索的json示例:

{
  "myObject": {
    "foo": "bar1",
    "foo": "bar2"
  }
}
下面是我在反序列化之后想要的:

{
  "myObject": {
    "foo": ["bar1","bar2"]
  }
}
我是这样创建我的类的:

public class MyObject {
    private List<String> foo;
    // constructor, getter and setter
}
这是我的
objectMapper
配置:

new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

有没有一种方法可以使用Jackson反序列化列表中的重复键?

您需要使用
com.fasterxml.Jackson.annotation.JsonAnySetter
annotation:

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class JsonPathApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        Root root = mapper.readValue(jsonFile, Root.class);
        root.getMyObject().getFoos().forEach(System.out::println);
    }
}

class Root {

    private MyObject myObject;

    // getters, setters, toString
}

class MyObject {

    private List<String> foos = new ArrayList<>();

    @JsonAnySetter
    public void manyFoos(String key, String value) {
        foos.add(value);
    }

    // getters, setters, toString
}
补充回答:如果您需要处理混合单个值和列表/映射的情况:

{  
  "myObject": {
     "foo": "bar1",
     "foo": ["bar2", "bar3"],
     "foo": {"bar": "baz"}
  }
}
这可以在相同的
manyFoos
中完成:

@SuppressWarnings("unchecked")
@JsonAnySetter
public void manyFoos(String key, Object value) {
    System.out.println("key = " + key + " -> " + value.getClass() + ": " + value);
    if (value instanceof String)
        foos.add((String)value);
    else if (value instanceof Collection<?>) {
        foos.addAll((Collection<? extends String>)value);
    }
    else if (value instanceof Map<?, ?>) {
        Map<? extends String, ? extends String> subFoo = (Map<? extends String, ? extends String>) value;
        subFoo.entrySet().forEach(e -> foos.add(e.getKey() + ":" + e.getValue()));  
    }
}

我认为使用
ObjectMapper
不可能不是有效的json。您必须使用
JsonParser
这里有一个可接受的答案应该有帮助@AlexRudenko我不想添加另一个依赖项,但它看起来像是另一个解决方案。@Oleg我可以尝试
JsonParser
,但我想我必须为此创建一个自定义反序列化程序。如果可能的话,我希望找到一个解决方案而不这样做。它看起来像我正在寻找的,但如何防止出现此错误
com.fasterxml.jackson.databind.exc.MismatchedInputException:无法反序列化'java.util.ArrayList'的实例,超出值\u字符串标记
?我试图添加这个
新的ObjectMapper().configure(反序列化功能.FAIL_ON_READING_DUP_TREE_KEY,false)
,但它似乎不起作用回答@MichałZiober@JsonMraz,这就是
@JsonAnySetter
正在做的事情。注意,属性名是
foos
而不是
foo
。因此,默认情况下,
Jackson
不会接触它,所有其他未映射的属性都被放入
manyFoos
方法。@MichałZiober对不起,我没有注意到带有“s”的
foos
。我用
@JsonAnySetter
添加了它,它可以工作了!谢谢!我尝试了这种方法,但我发现我的
@JsonAnySetter
注释方法在我
Sys.out
时没有得到重复的条目。我的意思是,当我在
@jsonanyster
带注释的方法中打印
时,即使是重复的
和最后一个值,我也只能看到一个条目。这就好像
Jackson
在使用此方法之前已经忽略了重复的条目。我已经把我的问题贴在这里了。一个机会,请让我知道我该怎么做。我尝试了这种方法,但我发现我的
@JsonAnySetter
注释方法在我
Sys.out
时没有得到重复的条目。我的意思是,当我为重复条目打印
时,我只看到重复键的最后一个值。这就好像
Jackson
在使用此方法之前已经忽略了重复的条目。我已经把我的问题贴在这里了。一个机会,请让我知道我该怎么做。
{  
  "myObject": {
     "foo": "bar1",
     "foo": ["bar2", "bar3"],
     "foo": {"bar": "baz"}
  }
}
@SuppressWarnings("unchecked")
@JsonAnySetter
public void manyFoos(String key, Object value) {
    System.out.println("key = " + key + " -> " + value.getClass() + ": " + value);
    if (value instanceof String)
        foos.add((String)value);
    else if (value instanceof Collection<?>) {
        foos.addAll((Collection<? extends String>)value);
    }
    else if (value instanceof Map<?, ?>) {
        Map<? extends String, ? extends String> subFoo = (Map<? extends String, ? extends String>) value;
        subFoo.entrySet().forEach(e -> foos.add(e.getKey() + ":" + e.getValue()));  
    }
}
{
  "myObject" : {
    "foos" : [ "bar1", "bar2", "bar3", "bar:baz" ]
  }
}