使用Jackson数据绑定跳过嵌套字段?

时间:2015-07-31 17:52:21

标签: java json jackson json-deserialization jsonserializer

如何将以下json片段与杰克逊下面的Java对象绑定(双向)?

我希望Json新闻稿节点的键/值对最终位于新闻稿字段的Map中。 什么是杰克逊配置(注释和其他)绑定这个? 对不起,我不知道如何:((使用最新版本的杰克逊)。

下面的Json格式是固定的,我是从第三方休息服务接收的(我无法更改)。我可以更改java代码,但更喜欢下面的设置。

JSON:

{
    "newsletter": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}

Java对象:

class Preferences {
    private NewsLetter newsLetter;
    // getter/setter for field newsLetter.
}

class NewsLettter {
    private Map<String, String> properties;
    // getter/setter for field properties.
}

4 个答案:

答案 0 :(得分:3)

您只需使用@JsonAnySetter进行反序列化

即可
  

标记注释,可用于定义非静态,双参数方法(属性的第一个参数名称,要设置的第二个值),用作从JSON找到的所有其他无法识别的属性的“回退”处理程序内容。

@JsonAnyGetter用于序列化。

  

标记注释,可用于将非静态,无参数方法或成员字段定义为JsonAnySetter方法的反向;基本上像getter一样使用但是返回的Map的内容(类型必须是Map)被序列化,好像它们是包含带有此注释的方法/字段的bean的实际属性

public class Newsletter {

    private final Map<String, String> properties = new HashMap<>();

    @JsonAnySetter
    public void addProperty(String name, String value) {
        properties.put(name, value);
    }

    @JsonAnyGetter
    public Map<String, String> getProperties() {
        return properties;
    }
}

这应该适用于您的用例。

测试

public class Main {

    public static void main(String[] args) throws Exception {
        String json
                = "{\n"
                + "    \"newsletter\": {\n"
                + "        \"key1\": \"value1\",\n"
                + "        \"key2\": \"value2\",\n"
                + "        \"key3\": \"value3\"\n"
                + "    }\n"
                + "}";

        ObjectMapper mapper = new ObjectMapper();
        Preferences prefs = mapper.readValue(json, Preferences.class);
        Map<String, String> properties = prefs.getNewsletter().getProperties();
        for (Map.Entry<String, String> prop: properties.entrySet()) {
            System.out.println(prop.getKey() + ":" + prop.getValue());
        }
    }
}

另见:

答案 1 :(得分:1)

如果你能够得到一个道具JSON,就像这样:

{
    "newsletter": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}

注意,作为分隔符,而不是;

然后您可以使用以下类来保存JSON数据:

class Preferences {
    @JsonProperty("newsletter")
    private Map<String, String> newsLetter;

    @Override
    public String toString() {
        return "Preferences{" + "newsLetter=" + newsLetter + '}';
    }
}

在这里,您不再使用NewsLetter类,因为您需要嵌套密钥,例如Roman C在他的回答中说。只需将Map字段直接添加到您的Preferences类中,它就可以正常工作。

你可以这样阅读你的JSON:

public static void main(String[] args) throws Exception {
    ObjectMapper om = new ObjectMapper();
    System.out.println(om.readValue(new File("example.json"), Preferences.class));
}

它会打印出来:

  

偏好设置{newsLetter = {key1 = value1,key2 = value2,key3 = value3}}

答案 2 :(得分:0)

以下是JSON到Java转换的工作原理

第一步是创建保存JSON数据的Java类。你已经有一个。看看json。您创建一个Preferences对象来保存 整个json。 json包含newsletter元素。您 在Newsletter对象中创建Preferences类型的Java对象。 创建org.codehaus.jackson.map.ObjectMapper类的实例。这是班级 将JSON映射到Java对象。

 ObjectMapper mapper = new ObjectMapper();

然后使用readValue的{​​{1}}方法阅读。这个方法有多个版本,您可以使用接受的方法 ObjectMapper。但是,有一种方法可以从StringURLFileInputStreamString中读取。

ByteArray缓存序列化程序和反序列化程序,因此最好将ObjectMapper实例重用于多个 转换 如果您有ObjectMapper,则将其传递给Jackson以将其转换为Java Object。

String

您可以使用将json转义为java字符串的工具:http://www.freeformatter.com/java-dotnet-escape.html

此工具会产生以下结果

String str = "
    { \"newsletter\":
      {
        \"properties\": {
         \"key1\" : \"value1\",
         \"key2\" : \"value2\",
         \"key3\" : \"value3\"
      }
     }
   }";

//read json
Preferences preferences = mapper.readValue(str, Preferences.class);
//write json
mapper.writeValue(str, preferences);

答案 3 :(得分:0)

我想我已经开始工作了。 我用

  • @JsonValue创建JSON的时事通讯部分。
  • @JsonCreator用地图创建NewsLetter实例 包含键/值对。
  • @JsonTypeInfo指示用于创建的实现 NewsLetter实例。

使用上面的json片段,测试运行良好,两种方式。 在代码中(首选项类与原始问题中列出的相同):

registered 1
registered 2
registered 3
registered 1 (verbatim, syncronous echo)
registered 2 (verbatim, syncronous echo)
registered 3 (verbatim, syncronous echo)

是这样做的吗?我之前从未使用过@JsonTypeInfo,所以我希望它是正确的。我会用谷歌更多的例子。感谢所有的反馈。