Jackson: 如何使用 @JsonAnySetter 注解与自定义反序列化器?

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

Jackson: How to use a custom deserializer with @JsonAnySetter annotation?

问题

我有几个YAML配置文件,我想将它们反序列化成一个类。文件中的YAML由简单的名称值对组成,没有嵌套。有一些属性将有明确的字段,但我只想将其余的内容放入Map中。

这一切都运行良好,但我还希望通过.add()反序列化到Map中的属性的所有值都经过自定义反序列化器处理。我尝试在setter值参数和setter方法本身上使用@JsonDeserialize,但Jackson似乎完全忽略了它。

设置如下:

  1. public class ConfigData {
  2. private Map<String, Object> dynamicConfig = new LinkedHashMap<>();
  3. @JsonAnyGetter
  4. public Map<String, Object> getConfig() {
  5. return dynamicConfig;
  6. }
  7. @JsonAnySetter
  8. public void add(String name, @JsonDeserialize(using = FooDeserializer.class) Object value) {
  9. dynamicConfig.put(name, value);
  10. }
  11. @JsonProperty("some_special_property")
  12. public String setSomeSpecialProperty(String value) {
  13. add("some_special_property", value);
  14. }
  15. }

用于反序列化的代码如下:

  1. public static ConfigData getConfig(URL configResource) throws IOException {
  2. try (InputStream stream = configResource.openStream()) {
  3. ObjectMapper mapper = new YAMLMapper();
  4. return mapper.readValue(new InputStreamReader(stream, StandardCharsets.UTF_8), ConfigData.class);
  5. }
  6. }
英文:

I have several YAML config files I want to deserialize into a class. The YAML in the files consists of simple name value pairs with no nesting. There's a handful of properties that will have explicit fields, but the rest I just want dumped into a Map.

This all works fine, but I also want all the values of the properties that get deserialized into the Map through .add() to be run through a custom deserializer. I've tried using @JsonDeserialize on the setter value parameter and the setter method itself but Jackson seems to ignore it altogether.

Here's how it's set up:

  1. public class ConfigData {
  2. private Map&lt;String, Object&gt; dynamicConfig = new LinkedHashMap&lt;&gt;();
  3. @JsonAnyGetter
  4. public Map&lt;String, Object&gt; getConfig() {
  5. return dynamicConfig;
  6. }
  7. @JsonAnySetter
  8. public void add(String name, @JsonDeserialize(using = FooDeserializer.class) Object value) {
  9. dynamicConfig.put(name, value);
  10. }
  11. @JsonProperty(&quot;some_special_property&quot;)
  12. public String setSomeSpecialProperty(String value) {
  13. add(&quot;some_special_property&quot;, value);
  14. }
  15. }

And to deserialize:

  1. public static ConfigData getConfig(URL configResource) throws IOException {
  2. try (InputStream stream = configResource.openStream()) {
  3. ObjectMapper mapper = new YAMLMapper();
  4. return mapper.readValue(new InputStreamReader(stream, StandardCharsets.UTF_8), ConfigData.class);
  5. }
  6. }

答案1

得分: 1

我发现问题是我在@JsonDeserialize注解的using属性中指定了反序列化器类。对于这种特定用例,我需要使用contentUsing属性,该属性用于像Map条目的值字段之类的情况。

这是我的setter现在的样子:

  1. @JsonAnySetter
  2. @JsonDeserialize(contentUsing = FooDeserializer.class)
  3. public void add(String name, Object value) {
  4. dynamicConfig.put(name, value);
  5. }

现在所有的值都将使用FooDeserializer进行序列化,除了"some_special_property",它有自己的setter。

英文:

I discovered the problem was that I was specifying the deserializer class with the using property of the @JsonDeserialize annotation. For this specific use case I needed to use the contentUsing property instead, which is used for things like the value field of a Map entry.

This is what my setter looks like now:

  1. @JsonAnySetter
  2. @JsonDeserialize(contentUsing = FooDeserializer.class)
  3. public void add(String name, Object value) {
  4. dynamicConfig.put(name, value);
  5. }

Now all the values will be serialized using FooDeserializer, except for &quot;some_special_property&quot; which has its own setter.

huangapple
  • 本文由 发表于 2020年7月30日 00:57:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63158709.html
匿名

发表评论

匿名网友

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

确定