如何解决Newtonsoft JSON自动映射特定属性
在序列化/反序列化过程中,遇到某种类型的属性时,是否有任何方法可以迫使newtonsoft交换类型?
如果我有以下内容:
public class SomeClass
{
public SomeNonSerializableType Property { get; set; }
}
如果在序列化过程中遇到SomeNonSerializableType
,我想使用自动映射器将其映射到SomeSerializableType
。我假设我可以使用合同解析器来执行此操作,但不确定如何实现它。然后,我需要反向执行同样的操作,例如,如果在反序列化过程中遇到SomeSerializableType
,请将其映射回SomeNonSerializableType
。
解决方法
您可以创建一个custom generic JsonConverter
,该序列会在序列化过程中自动从某些模型映射到DTO类型,并在反序列化过程中自动映射回DTO类型,例如:
public class AutomapperConverter<TModel,TDTO> : JsonConverter
{
static readonly Lazy<MapperConfiguration> DefaultConfiguration
= new Lazy<MapperConfiguration>(() => new MapperConfiguration(cfg => cfg.CreateMap<TModel,TDTO>().ReverseMap()));
public AutomapperConverter(MapperConfiguration config) => this.config = config ?? throw new ArgumentNullException(nameof(config));
public AutomapperConverter() : this(DefaultConfiguration.Value) { }
readonly MapperConfiguration config;
public override bool CanConvert(Type type) => type == typeof(TModel);
public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
{
var dto = config.CreateMapper().Map<TDTO>(value);
serializer.Serialize(writer,dto);
}
public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
{
var dto = serializer.Deserialize<TDTO>(reader);
return config.CreateMapper().Map(dto,dto.GetType(),objectType);
}
}
然后将具体实例添加到JsonSerializerSettings.Converters
中,如下所示:
// Configure this statically on startup
MapperConfiguration configuration
= new MapperConfiguration(cfg =>
{
// Add all your mapping configurations here.
// ReverseMap() ensures you can map from and to the DTO
cfg.CreateMap<SomeNonSerializableType,SomeSerializableType>().ReverseMap();
});
// Set up settings using the global configuration.
var settings = new JsonSerializerSettings
{
Converters = { new AutomapperConverter<SomeNonSerializableType,SomeSerializableType>(configuration) },};
var json = JsonConvert.SerializeObject(someClass,Formatting.Indented,settings);
var deserialized = JsonConvert.DeserializeObject<SomeClass>(json,settings);
注意:
-
该转换器不适用于处理多态性。
-
转换器不支持preservation of object references,但可以通过使用
JsonSerializer.ReferenceResolver
来扩展它,如 JsonConverter resolve reference 或所示。 Custom object serialization vs PreserveReferencesHandling 。 -
每个AppDomain只能配置一次。
但是,如果未传递任何默认值,则转换器将配置默认映射。
演示小提琴here。
,昨天我不得不做类似的事情。尽管就我而言,我只需要更改属性名称映射,但是您可以使用JsonConverter
更改类型,如下所示:
public enum UserStatus
{
NotConfirmed,Active,Deleted
}
public class User
{
public string UserName { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public UserStatus Status { get; set; }
}
根据reference:
JsonConverterAttribute JsonConverterAttribute指定哪个JsonConverter用于转换对象。 该属性可以放在类或成员上。当放置在一个类上时,该属性指定的JsonConverter将是序列化该类的默认方法。当属性位于字段或属性上时,将始终使用指定的JsonConverter来序列化该值。 使用JsonConverter的优先级是成员属性,然后是类属性,最后是传递给JsonSerializer的所有转换器。
根据class reference,类型为System.Type。
听起来似乎没有必要,但JsonConstructorAttribute
也可能是有趣的:
JsonConstructorAttribute指示JsonSerializer在反序列化类时使用特定的构造函数。它可以用于使用参数化构造函数而不是默认构造函数创建类,或者在存在多个参数的情况下选择要使用的特定参数化构造函数:
public class User
{
public string UserName { get; private set; }
public bool Enabled { get; private set; }
public User()
{
}
[JsonConstructor]
public User(string userName,bool enabled)
{
UserName = userName;
Enabled = enabled;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。