java - @JsonUnwrapped 用于自定义序列化器

标签 java json jackson

我有一个相对复杂的对象,其中包含许多字段。我需要使用自定义序列化程序序列化其中一个字段,但需要模拟 @JsonUnwrapped 功能。

为了简单起见,我将其削减为两个字段:

public class MyClass
{
  @JsonProperty("subject")
  private final String subject;
  @JsonSerialize(using=MySenderSerializer.class)
  private final MailActor sender;
}

我的自定义序列化器类如下:

public class MySenderSerializer extends StdSerializer<MailActor>
{
  public MySenderSerializer()
  {
    super(MailActor.class, true);
  }

  @Override
  public void serialize(final MailActor value, final JsonGenerator gen, final SerializerProvider provider) throws IOException
  {
    gen.writeStringField("from_name", value.getName());
    gen.writeStringField("from_email", value.getAddress());
  }
}

所有这些都很好,除了输出 JSON 如下所示:

{
  ...
  "subject": "test subject",
  "sender": {
    "from_name": "test from",
    "from_email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8cf8e9fff8ccf8e9fff8a2efe3e1" rel="noreferrer noopener nofollow">[email protected]</a>"
  },
  ...
}

我需要解开 sender 字段,以便 JSON 如下所示:

{
  ...
  "subject": "test subject",
  "from_name": "test from",
  "from_email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="384c5d4b4c784c5d4b4c165b5755" rel="noreferrer noopener nofollow">[email protected]</a>",
  ...
}

如果我使用标准序列化器,我可以使用 @JsonUnwrapped 注释来执行此操作,但它似乎与自定义序列化器不兼容。如何在不为 MyClass 对象编写自定义序列化器的情况下获得所需的 JSON 输出?

最佳答案

我也必须寻找@JsonUnwrapped的替代方案,因为它给我带来了一些与这个问题无关的问题。

我实现的解决方案同样适用于您的情况,使用@JsonAnyGetter。在您的 MyClass 中,忽略需要特殊序列化的属性,而是使用 JsonAnyGetter 添加它:

public class MyClass
{
    @JsonProperty("subject")
    private final String subject;
    @JsonIgnore
    private final MailActor sender;

    @JsonAnyGetter
    public Map<String, Object> serializeActor() {
         return sender.serializeToMap();
         // Of course, here you could create an empty map
         // and add the properties of many different classes.
    }
}

然后在 MailActor 类中实现该方法,该方法将返回一个包含您可能需要的属性的映射。

public Map<String, Object> serializeToMap() {
    final Map<String, Object> properties = new ArrayMap<>();
    properties.put("from_name", this.getName());
    properties.put("from_email", this.getAddress());
    return properties;
}

这种方式的问题是反序列化对象,因为 @JsonAnySetter 不会像上面示例中给出的那样获取带有 JSON 的映射。在你的情况下,这甚至更加困难,因为你的类(class)属性是最终的。您需要使用 @JsonCreator 来创建所有属性。大致如下:

@JsonCreator
public MyClass( Map< String, String > json ) {
    if (json.containsKey("subject")) {
        subject = json.get("subject");
    } else {
        subject = "";
    }

    String name, address;
    if (json.containsKey("from_name")) {
        name = json.get("from_name");
    } else {
        name = "";
    }
    if (json.containsKey("from_email")) {
        address = json.get("from_email");
    } else {
        address = "";
    }
    sender = new MailActor(name, address);
}

自从您发布问题以来已经有一段时间了,希望这对寻求替代方案的人有所帮助。

关于java - @JsonUnwrapped 用于自定义序列化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26959816/

相关文章:

java - 使用 isEmpty() 方法时获取空指针异常

json - 从 Redshift 表中获取 JSON 数据

java - 用于接口(interface)的 Kafka JSON 反序列化器

c# - Newtonsoft Json 序列化程序无法使用继承自 List 的自定义类

json - 如何以可重用的方式使用kotlin比较使用键属性的2个Json对象文件?

rest - 如何将文件与包含有关文件的附加信息的对象的 json 一起上传?

java - 通用 map 中的 Jackson De/Serializing Date-to-String-to-Date

java - 为什么 "boolean inclusive"版本的 NavigableSet 返回 NavigableSet,而那些没有 "boolean inclusive"版本的 NavigableSet 返回 SortedSet?

java - 如何使用来自 postgres 的带时区的 unix 时间戳格式化 D3 轴

java - OneLogin java-saml-tookit-jspsample 在解析响应时崩溃