使用Jackson反序列化具有重复键的JSON

huangapple go评论91阅读模式
英文:

Deserialize json with duplicate keys using Jackson

问题

Sure, here's the translation of the content you provided:

我正在尝试使用Jackson解析一个带有重复键的JSON数据,将其转换为Map<String, List<String>>类型。

考虑以下数据:

{
    "foo" : "val1",
    "foo" : "val2",
    "bar" : "val3"
}

我希望将其转换为Map<String, List<String>>类型,示例如下:

+--------------+----------------------+
| 键 (String)  | 值 (List<String>)   |
+--------------+----------------------+
| foo          | [val1, val2]         |
| bar          | [val3]               |
+--------------+----------------------+

在使用Jackson处理这种情况时,最好的方法是什么?我希望在Jackson中有一种方法,可以为Map<String, List<String>>类型注册自定义的反序列化逻辑。(请注意,我无法控制请求中发送的JSON数据)

非常感谢您的帮助。

英文:

I am trying to parse a json payload with duplicate keys to a Map&lt;String, List&lt;String&gt;&gt; using Jackson

Consider the following payload

{
&quot;foo&quot; : &quot;val1&quot;,
&quot;foo&quot; : &quot;val2&quot;,
&quot;bar&quot; : &quot;val3&quot;
}

I want to convert this to a Map&lt;String, List&lt;String&gt;&gt; type.

ex:

+--------------+----------------------+
| Key (String) | Value (List&lt;String&gt;) |
+--------------+----------------------+
| foo          | [val1, val2]         |
| bar          | [val3]               |
+--------------+----------------------+

What would be the best way to handle this with Jackson? I'm hoping that there's a way in Jackson where I can register a custom deserialization logic for Map&lt;String, List&lt;String&gt;&gt; type. (Note that I have no control over the json payload sent in the request)

Appreciate any help on this.

Thanks!

答案1

得分: 1

检查它是否适用于您。

使用 @JsonAnySetter 来反序列化未映射的 JSON 属性。@JsonAnySetter 注解可用于定义“任何设置器”变异器。

使用 @JsonAnyGetter 注解来序列化任何任意属性。@JsonAnyGetter 可用于返回 Map 的方法上。

POJO 定义

Test.java

package oct2020.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;

public class Test {

    private Map<String, List<String>> keyValuesMap = new HashMap<String, List<String>>();

    /**
     * @return the keyValuesMap
     */
    @JsonAnyGetter
    public Map<String, List<String>> getKeyValuesMap() {
        return keyValuesMap;
    }

    /**
     * @param keyValuesMap the keyValuesMap to set
     */
    public void setKeyValuesMap(Map<String, List<String>> keyValuesMap) {
        this.keyValuesMap = keyValuesMap;
    }

    @JsonAnySetter
    public void duplicateKeyValues(String key, String value) {
        List<String> values = null;
        if (!keyValuesMap.containsKey(key)) {
            values = new ArrayList<String>();
        } else {
            values = keyValuesMap.get(key);
        }
        values.add(value);
        keyValuesMap.put(key, values);
    }
}

将 JSON 转换为所需格式。

JSONConverter.java

package oct2020.json;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;

public class JSONConverter {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"foo\" : \"val1\",\"foo\" : \"val2\",\"bar\" : \"val3\","
                + "\"bar\" : \"val3\",\"bar\" : \"val3\",\"bar\" : \"val3\","
                + "\"bar\" : \"val3\",\"bar\" : \"val3\",\"bar\" : \"val3\","
                + "\"bar\" : \"val3\",\"bar\" : \"val3\"}";
        Test test = mapper.readValue(json, Test.class);
        Map<String, List<String>> keyValuesMap = test.getKeyValuesMap();
        System.out.println(mapper.writerWithDefaultPrettyPrinter()
                .writeValueAsString(keyValuesMap));
    }
}

输出:

{
  "bar" : [ "val3", "val3", "val3", "val3", "val3", "val3", "val3", "val3", "val3", "val3" ],
  "foo" : [ "val1", "val2" ]
}
英文:

Check if it works for you.

Using @JsonAnySetter to deserialize unmapped JSON properties. @JsonAnySetter annotation can be used to define "any setter" mutator.

Using @JsonAnyGetter Annotation to serialize any arbitrary properties. @JsonAnyGetter can be used on a method which returns a Map.

POJO Definition

Test.java

package oct2020.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;

public class Test {
	
	private Map&lt;String, List&lt;String&gt;&gt; keyValuesMap = new HashMap&lt;String, List&lt;String&gt;&gt;();

	/**
	 * @return the keyValuesMap
	 */
	@JsonAnyGetter
	public Map&lt;String, List&lt;String&gt;&gt; getKeyValuesMap() {
		return keyValuesMap;
	}

	/**
	 * @param keyValuesMap
	 *            the keyValuesMap to set
	 */
	public void setKeyValuesMap(Map&lt;String, List&lt;String&gt;&gt; keyValuesMap) {
		this.keyValuesMap = keyValuesMap;
	}

	@JsonAnySetter
	public void duplicateKeyValues(String key, String value) {
		List&lt;String&gt; values = null;
		if (!keyValuesMap.containsKey(key)) {
			values = new ArrayList&lt;String&gt;();
		} else {
			values = keyValuesMap.get(key);
		}
		values.add(value);
		keyValuesMap.put(key, values);
	}
}

Converting the json to desired format.

JSONConverter .java

package oct2020.json;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;

public class JSONConverter {
	public static void main(String[] args) throws IOException {
		ObjectMapper mapper = new ObjectMapper();
		String json = &quot;{\n\&quot;foo\&quot; : \&quot;val1\&quot;,\n\&quot;foo\&quot; : \&quot;val2\&quot;,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,&quot;
				+ &quot;\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,&quot;
				+ &quot;\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,&quot;
				+ &quot;\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;\n,\n\&quot;bar\&quot; : \&quot;val3\&quot;}&quot;;
		Test test = mapper.readValue(json, Test.class);
		Map&lt;String, List&lt;String&gt;&gt; keyValuesMap = test.getKeyValuesMap();
		System.out.println(mapper.writerWithDefaultPrettyPrinter()
				.writeValueAsString(keyValuesMap));
	}
}

Output:

{
  &quot;bar&quot; : [ &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot;, &quot;val3&quot; ],
  &quot;foo&quot; : [ &quot;val1&quot;, &quot;val2&quot; ]
}

答案2

得分: 0

请将此属性JsonTypeInfo.As.EXISTING_PROPERTY放入@JsonTypeInfo注释中。可能会起作用。

英文:

please put this property JsonTypeInfo.As.EXISTING_PROPERTY in the @JsonTypeInfo annotation. It might work.

huangapple
  • 本文由 发表于 2020年10月3日 14:36:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/64181422.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定