反序列化具有一个元素的列表,如果列表大小为 1,则直接作为元素本身(Json 格式)

Posted

技术标签:

【中文标题】反序列化具有一个元素的列表,如果列表大小为 1,则直接作为元素本身(Json 格式)【英文标题】:Deserialize a list with one element, directly as the element itself in case the list size is 1 (Json format) 【发布时间】:2020-01-13 18:27:26 【问题描述】:

在 Spring Boot 应用程序中,我有一个名为 Resource.java 的 DTO 类,其中包含一个字符串列表。在 GET REST Web 服务中,当我返回 Resource 对象时,如果列表的大小等于 1,我希望将其直接反序列化为字符串本身,而不是作为具有一个元素的列表。

我已经使用 @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 处理了这种情况的序列化。

是否有任何类似的反序列化工作?

@Data
public class Resource 

    private String id;
    private String name;
    @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
    @JsonAlias("foo", "foos")
    private List<String> foos;

当前: “id”:“22”, “名称”:“汤姆”, “钩子网址”:[ “http:blabla” ]

要求: “id”:“22”, “名称”:“汤姆”, “hookUrls”:“http:blabla”

【问题讨论】:

请问您为什么要实现这个目标?看到这样的 API 非常不寻常/令人惊讶。如果某些东西可能包含多个值,老实说,它应该始终是一个列表。您甚至必须启用特定的映射功能来支持这一点 已有一个 API 使用带有字符串 foo 的资源,而不是我示例中的列表。但是我需要为一些想要在其中附加多个 foo 值的新客户端调整这个 API,但同时我也需要为旧客户端的请求保持不变。如果解决方案过于复杂,我将创建一个具有列表 foos 的单独资源 DTO,并将在新客户端的新 v2 API 中使用。 This 序列化功能应该适合你 【参考方案1】:

启用WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED 功能,其行为与您描述的完全一样。见here。

您需要为此创建自己的ObjectMapper。要覆盖 Spring 的默认 ObjectMapper,只需在 @Configuration 类中定义一个 @Bean,该类返回 ObjectMapper 并启用给定的功能。

【讨论】:

有什么方法可以将此配置限制为我的资源 bean 中的特定列表字段?我不想为所有其他 bean 更改 ObjectMapper 的逻辑。 您也可以像使用 ACCEPT_SINGLE_VALUE_AS_ARRAY 一样将功能传递给 JsonFormat.Feature 见here

以上是关于反序列化具有一个元素的列表,如果列表大小为 1,则直接作为元素本身(Json 格式)的主要内容,如果未能解决你的问题,请参考以下文章

杰克逊将单个项目反序列化为列表

具有列表值的列,如果列表具有超过 1 个元素,则解码这两个值并包含在新列的同一行中的列表中

序列化与反序列化的应用

如何反序列化列表以获取元素值

Flutter反序列化列表的列表

反序列化在不同 MailChimp 列表中具有不同名称的合并字段和兴趣