放弃使用特定键序列化映射条目
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】:您应该在序列化时使用有问题的类修复实际的双向映射。例如,如果您的类 ContentObject 和 BackReferringObject 相互引用,您可以使用@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 会导致另一个自定义序列化程序的递归调用链并再次导致堆栈溢出。
我意识到这并不直接适用于地图,而是作为示例
【讨论】:
以上是关于放弃使用特定键序列化映射条目的主要内容,如果未能解决你的问题,请参考以下文章
在 DirectByteBuffer 中存储 Big Hashmap 的方法