如何将 Jackson 的 @JsonAnySetter 与记录类一起使用?

问题描述 投票:0回答:1

我正在尝试使用杰克逊的功能将未知字段反序列化到地图中,使用

@JsonAnySetter
。这对于字段用
@JsonAnySetter
注释的 Java 类来说效果很好,但不适用于记录:

public class SerdeTest {
    private static final String CONTENT = "{ \"name\": \"foo\", \"bar\": \"baz\" }";

    private ObjectMapper om = new ObjectMapper();

    static class ThisWorks {
        public String name;
        @JsonAnySetter Map<String, String> others;
    }

    @Test
    public void deserClass() throws IOException {
        var data = om.readValue(CONTENT, ThisWorks.class);

        assertThat(data.name, equalTo("foo"));
        assertThat(data.others.get("bar"), equalTo("baz"));
    }

    record ThisDoesnt(String name, @JsonAnySetter Map<String, String> others) {}

    @Test
    public void deserRecord() throws IOException {
        var data = om.readValue(CONTENT, ThisDoesnt.class);

        assertThat(data.name, equalTo("foo"));
        assertThat(data.others.get("bar"), equalTo("baz"));
    }
}

如何将此注释与记录一起使用?

java jackson java-16
1个回答
0
投票

简短回答

记录尚未像您期望的那样干净地支持

@JsonAnySetter
- 参考此 GitHub 问题

长答案

恕我直言,使用

record
类型的概念与您与
@JsonAnySetter Map<String, String> others
一起寻求的灵活性相矛盾。虽然您使用减少的样板代码来声明不可变类型,但另一方面,在实践中您正在寻求更新实体的属性而不遵守固定的构造。

作为链接线程的替代方案,您可以尝试重写

others
属性的自定义构造函数和访问器,如下所示以使其工作:

record ThisDoes(String name, @JsonAnySetter Map<String, String> others) {

    @JsonCreator
    ThisDoes(@JsonProperty("name") String name) {
        this(name, new HashMap<>());
    }

    public Map<String, String> others() {
        return Collections.unmodifiableMap(others);
    }

    @JsonAnySetter
    private void updateProperty(String name, String value) {
        others.put(name, value);
    }
}

(用

v-2.15.3
验证)

但请注意,这也消除了在向

record
表示迁移期间可能寻求的好处的样板代码的减少。

© www.soinside.com 2019 - 2024. All rights reserved.