.NET6中AutoMapper映射JsonObject报错:The node already has a parent
问题场景
使用AutoMapper 12.0.0映射包含System.Text.Json.Nodes.JsonObject属性的record类型时,抛出以下错误:
System.InvalidOperationException: The node already has a parent.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_NodeAlreadyHasParent()
at System.Text.Json.Nodes.JsonNode.AssignParent(JsonNode parent)
at lambda_method319(Closure , Object , ResultsEvent, ResolutionContext )
源类型定义:
public record Request { public Guid RequestId { get; set; } public JsonObject AdditionalParameters { get; set; } }
目标类型定义:
public record ResultsEvent { public Guid RequestId { get; init; } public JsonObject AdditionalParameters { get; init; } }
执行以下映射代码时触发错误:
var resultsEvent = _mapper.Map<ResultsEvent>(request);
已尝试克隆JsonObject、序列化反序列化等方法,均未解决,希望得到无需手动逐个配置映射规则的优雅方案。
优雅解决方案:全局注册JsonObject类型转换器
AutoMapper默认会直接引用源JsonObject实例,但JsonObject内部维护了父节点关联,同一实例无法被多个父对象引用。通过全局注册自定义类型转换器,让AutoMapper自动克隆JsonObject,所有涉及JsonObject的映射都会自动生效,无需单独配置每个映射规则。
1. 实现ITypeConverter接口
using AutoMapper; using System.Text.Json.Nodes; public class JsonObjectConverter : ITypeConverter<JsonObject, JsonObject> { public JsonObject Convert(JsonObject source, JsonObject destination, ResolutionContext context) { return source?.Clone() as JsonObject; } }
2. 在AutoMapper配置中全局注册转换器
var configuration = new MapperConfiguration(cfg => { // 全局注册JsonObject的类型转换器 cfg.CreateMap<JsonObject, JsonObject>().ConvertUsing<JsonObjectConverter>(); // 注册业务类型的映射规则 cfg.CreateMap<Request, ResultsEvent>(); }); var _mapper = configuration.CreateMapper();
配置完成后,AutoMapper在处理JsonObject类型映射时会自动调用克隆逻辑,确保每个目标对象获取的是独立的JsonObject实例,彻底解决父节点冲突问题。
为何之前的克隆尝试无效?
如果之前是在映射代码中手动克隆JsonObject,AutoMapper的默认映射逻辑可能会覆盖该操作。通过全局注册类型转换器,让AutoMapper优先使用自定义的克隆逻辑,保证映射过程中始终生成独立的JsonObject实例。
内容的提问来源于stack exchange,提问作者Almog Zemach

