Java 使用Jackson反序列化要列出的重复密钥
我正在尝试将json反序列化为对象。但是,json有重复的键。我无法更改json,我想使用Jackson将重复键更改为列表 以下是我检索的json示例: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
{
"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" ]
}
}