放弃使用特定键序列化映射条目

Posted

技术标签:

【中文标题】放弃使用特定键序列化映射条目【英文标题】:Discard serializing a map entry with a specific key 【发布时间】:2022-01-10 06:40:02 【问题描述】:

我有一张需要序列化的地图,但是当我对其进行序列化时,我得到了jackson infinite recursion (***error)。因此,经过一段时间的调试,我找到了导致此问题的条目,但该条目是一个列表,其中包含具有一些循环依赖关系的其他对象。

让我在这里写一个示例代码。

Map<String, ?> params = new HashMap();
// Create some list and add objects with cyclic dependencies to it.
List<ContentObject> problematicList = new ArrayList();
//list.addAll(some problematic objects);

params.put("contentsModified", problematicList);
objectmapper.writeValueAsString(params); // here I get jackson infinite recursion (***error)

我尝试使用@JsonIgnoreType 标记我在problemList 中找到的对象的类,但它不起作用。有没有办法编写一些自定义序列化程序来查看映射是否包含名称为 contentsModified 的条目,如果找到这样的条目,它不会序列化有问题的列表?

【问题讨论】:

【参考方案1】:

您应该在序列化时使用有问题的类修复实际的双向映射。例如,如果您的类 ContentObjectBackReferringObject 相互引用,您可以使用@JsonBackReference,例如:

public class ContentObject 
    private String name = "contentsModified";
    private BackReferringObject backReferringObject;


public class BackReferringObject 
    @JsonBackReference
    private ContentObject contentObject;

这告诉杰克逊不要再次序列化contentObject

如果这是不可能的,你总是可以编写一些自定义序列化程序。那会让事情变得更复杂。例如,你可以有这样的东西:

public class ContentObjectSerializer extends JsonSerializer<ContentObject> 
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void serialize(ContentObject value, JsonGenerator gen, 
                              SerializerProvider serializers)
            throws IOException 
        if (!value.getName().equals("contentsModified")) 
            var sw = new StringWriter();
            objectMapper.writeValue(sw, value);
            gen.writeRawValue(sw.toString());
        
    

及用法:

var objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(ContentObject.class, new ContentObjectSerializer());
objectMapper.registerModule(module);

确实需要后一种配置。例如,您不能使用 @JsonSerialize(using = ContentObjectSerializer.class) 注释您的 ContentObject,因为那时自定义序列化程序中的 ObjectMapper 会导致另一个自定义序列化程序的递归调用链并再次导致堆栈溢出。

我意识到这并不直接适用于地图,而是作为示例

【讨论】:

以上是关于放弃使用特定键序列化映射条目的主要内容,如果未能解决你的问题,请参考以下文章

Clojure:如何将映射条目的惰性序列转换为结构映射?

YAML集合和结构

在 DirectByteBuffer 中存储 Big Hashmap 的方法

如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构

如果枚举映射键为空或未知,则忽略 JSON 反序列化

如何从 Hive 盒对象中获取密钥并将其映射到对象的特定字段?