C#中Record的复杂JSON序列化与反序列化问题
问题原因分析
当你给AmountPayed标记[JsonConverter(typeof(AmountPayedConverter))]后,序列化MyObject时,JsonSerializer会先为AmountPayed属性写入键名"AmountPayed":,再调用自定义转换器的Write方法。但你的转换器直接向写入器输出了"Currency"和"Amount"两个键值对,导致JSON结构变成"AmountPayed": "Currency": "EUR", "Amount": 1000——这完全违反JSON语法规则,既生成了无效JSON,又保留了多余的AmountPayed字段。
解决方案
要实现将AmountPayed的属性平级嵌入MyObject的JSON结构中,需要从父对象层面控制序列化逻辑,以下是两种可行方案:
方案一:为MyObject编写自定义转换器
通过自定义MyObject的序列化逻辑,直接将AmountPayed的属性展开到根JSON对象中:
[JsonConverter(typeof(MyKeyConverter))] record MyKey(Guid Value); record AmountPayed(string Currency, decimal Value); [JsonConverter(typeof(MyObjectConverter))] record MyObject(MyKey Id, string Name, AmountPayed AmountPayed); class MyKeyConverter : JsonConverter<MyKey> { public override MyKey Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { throw new NotImplementedException(); } public override void Write(Utf8JsonWriter writer, MyKey value, JsonSerializerOptions options) { writer.WriteStringValue(value.Value); } } class MyObjectConverter : JsonConverter<MyObject> { public override MyObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 如需反序列化,可在此处补全逻辑:读取Currency和Amount构造AmountPayed,再构造MyObject throw new NotImplementedException(); } public override void Write(Utf8JsonWriter writer, MyObject value, JsonSerializerOptions options) { writer.WriteStartObject(); // 序列化Id(复用MyKey的转换器) writer.WritePropertyName("Id"); JsonSerializer.Serialize(writer, value.Id, options); // 序列化Name writer.WriteString("Name", value.Name); // 展开AmountPayed的属性 writer.WriteString("Currency", value.AmountPayed.Currency); writer.WriteNumber("Amount", value.AmountPayed.Value); writer.WriteEndObject(); } }
序列化后得到的JSON符合预期:
{ "Id": "0748f992-4187-4006-98ed-d5cb0355f99c", "Name": "My Name", "Currency": "EUR", "Amount": 1000 }
方案二:结合JsonIgnore与计算属性
利用Record的特性,添加映射到AmountPayed属性的计算字段,同时忽略原AmountPayed属性:
[JsonConverter(typeof(MyKeyConverter))] record MyKey(Guid Value); record AmountPayed(string Currency, decimal Value); record MyObject(MyKey Id, string Name, AmountPayed AmountPayed) { [JsonPropertyName("Currency")] public string Currency => AmountPayed.Currency; [JsonPropertyName("Amount")] public decimal Amount => AmountPayed.Value; [JsonIgnore] public AmountPayed AmountPayed => AmountPayed; } class MyKeyConverter : JsonConverter<MyKey> { public override MyKey Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { throw new NotImplementedException(); } public override void Write(Utf8JsonWriter writer, MyKey value, JsonSerializerOptions options) { writer.WriteStringValue(value.Value); } }
这种方式无需编写复杂的转换器,仅通过属性标记即可实现平级序列化,适合简单场景。
内容的提问来源于stack exchange,提问作者Paulo Aboim Pinto
相关产品推荐
相关产品推荐

