如何覆盖属性的 JSON 序列化,将值序列化为字符串而不是对象?
Posted
技术标签:
【中文标题】如何覆盖属性的 JSON 序列化,将值序列化为字符串而不是对象?【英文标题】:How can I override the JSON serialization for a property, to serialize the value as a string instead of an object? 【发布时间】:2021-03-04 12:41:26 【问题描述】:使用 .Net 4.8,我的所有实体框架类都继承自 AbstractBase:
public abstract class AbstractBase
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id get; set;
public virtual DateTime CreatedTimestamp get; set;
public virtual DateTime UpdatedTimestamp get; set;
[Required]
public virtual int CreatedBy get; set;
[Required]
public virtual int LastModifiedBy get; set;
public virtual bool ActiveFlag get; set;
[JsonIgnore]
public virtual User CreatedByUser get; set;
[JsonIgnore]
public virtual User LastModifiedByUser get; set;
public string ToActiveInactive()
return this.ActiveFlag ? "Active" : "Inactive";
现在你可以看到我忽略了CreatedByUser
和LastModifiedByUser
。
我想做的是以某种方式替换 User 对象
具有名为 FullName 的属性
User 对象可以提供的类似
User test = new User();
test.GetFullName();
我的 User 对象已经有了这个,所以我的问题是有没有办法做到这一点,这样我就不必在每次想要序列化实体类时编写更多相同逻辑的实现?
【问题讨论】:
"用用户对象可以提供的名为 FullName 的属性替换用户对象是什么意思" 是什么意思?您的示例代码没有解释这一点。你的意思是你想给AbstractBase
一个属性string FullName => CreatedByUser.GetFullName();
?
【参考方案1】:
您可以创建一个自定义JsonConverter<T>
,就像Newtonsoft documentation 中显示的那样,将您的User
类序列化为字符串:
public class UserConverter : JsonConverter<User>
public override void WriteJson(JsonWriter writer, User value, JsonSerializer serializer)
writer.WriteValue(value.GetFullName());
public override User ReadJson(JsonReader reader, Type objectType, User existingValue, bool hasExistingValue, JsonSerializer serializer)
var fullName = serializer.Deserialize<string>(reader);
// Or construct a User and return it, if you can do so from the fullName.
throw new NotImplementedException();
请注意,您的问题没有为我提供足够的信息来编写 ReadJson()
方法。如果需要支持反序列化,则需要通过从fullName
字符串构造User
来完全实现此方法。
现在,要使用转换器,您有多种选择:
如果您只想将AbstractBase
的User
属性序列化为字符串,请使用JsonConverterAttribute
将转换器应用于User
属性,如下所示:
public abstract class AbstractBase
[JsonConverter(typeof(UserConverter))]
public virtual User CreatedByUser get; set;
[JsonConverter(typeof(UserConverter))]
public virtual User LastModifiedByUser get; set;
// Remaining properties and methods unchanged
如果您希望User
of 的所有实例都被序列化为字符串,您可以将其直接应用于User
,如下所示:
[JsonConverter(typeof(UserConverter))]
public class User
// Properties and methods unchanged
或者,您可以将其添加到您的 asp.net-web-api2 全局 JsonSerializerSettings.Converters
。要在 .NET Framework 中执行此操作,请参阅 Andrei 的 this answer 到 Json.net global settings。对于 .NET Core 2.x,请参阅 this answer 到 Customizing response serialization in ASP.NET Core MVC 由 Métoule。
.NET Core 3.x 及更高版本使用不同的序列化程序system.text.json,因此您必须在该版本中使用不同的方法,或者恢复使用 Json.NET,如 Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0? 所示.
演示小提琴here.
【讨论】:
以上是关于如何覆盖属性的 JSON 序列化,将值序列化为字符串而不是对象?的主要内容,如果未能解决你的问题,请参考以下文章
序列化为 JSON 字符串时如何修复 OutOfMemoryException?
为啥使用 Json.NET 序列化为 json 字符串时缺少 DriveInfo 的属性?
如何在 json 序列化时使用 DefaultContractResolver 覆盖具有字符串值的复杂类型属性
JSON.NET 将对象 序列化为 JSON字符串时,能否指定,某个属性不被转化。