如何自定义JSON序列化,将MetadataContextViewModel的Name设为对象键?
可行实现方案
方案1:自定义JSON转换器(推荐)
无需修改原MetadataContextViewModel结构,通过自定义转换器直接控制序列化/反序列化逻辑,适配System.Text.Json或Newtonsoft.Json两种常用库:
针对System.Text.Json的实现
public class MetadataContextViewModelConverter : JsonConverter<MetadataContextViewModel> { // 反序列化逻辑:将键值对结构转回原数组格式 public override MetadataContextViewModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var dict = JsonSerializer.Deserialize<Dictionary<string, IdTypeModel>>(ref reader, options); return new MetadataContextViewModel { Items = dict.Select(kv => new MetadataItemViewModel { Name = kv.Key, Id = kv.Value.Id, Type = kv.Value.Type }).ToList() }; } // 序列化逻辑:将数组转成键值对结构 public override void Write(Utf8JsonWriter writer, MetadataContextViewModel value, JsonSerializerOptions options) { writer.WriteStartObject(); foreach (var item in value.Items) { writer.WriteStartObject(item.Name); writer.WriteNumber("id", item.Id); writer.WriteString("type", item.Type); writer.WriteEndObject(); } writer.WriteEndObject(); } }
使用方式:给MetadataContextViewModel添加特性[JsonConverter(typeof(MetadataContextViewModelConverter))],或序列化时手动传入转换器。
针对Newtonsoft.Json的实现
public class MetadataContextViewModelConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(MetadataContextViewModel); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var dict = serializer.Deserialize<Dictionary<string, IdTypeModel>>(reader); return new MetadataContextViewModel { Items = dict.Select(kv => new MetadataItemViewModel { Name = kv.Key, Id = kv.Value.Id, Type = kv.Value.Type }).ToList() }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var model = (MetadataContextViewModel)value; writer.WriteStartObject(); foreach (var item in model.Items) { writer.WritePropertyName(item.Name); serializer.Serialize(writer, new { id = item.Id, type = item.Type }); } writer.WriteEndObject(); } }
使用方式:同样给ViewModel添加[JsonConverter(typeof(MetadataContextViewModelConverter))]特性,或在序列化配置中注入转换器。
方案2:通过AutoMapper直接映射到目标结构
利用已有的AutoMapper,直接将原实体/ViewModel映射为字典或匿名类型,序列化后自然得到目标JSON:
// 配置映射规则:从Domain实体直接转成键值对字典 CreateMap<MetadataContext, Dictionary<string, IdTypeModel>>() .ConvertUsing(src => src.Items.ToDictionary( item => item.Name, item => new IdTypeModel { Id = item.Id, Type = item.Type } )); // 或者映射到匿名类型(无需定义额外类) CreateMap<MetadataContext, object>() .ConvertUsing(src => src.Items.ToDictionary( item => item.Name, item => new { id = item.Id, type = item.Type } ));
后续直接序列化这个映射后的字典/匿名对象即可,原ViewModel可保留用于其他业务场景。
方案3:序列化专用包装类
如果不想修改原ViewModel也不想写转换器,可以做一个轻量包装类,利用JsonExtensionData特性实现动态键值对:
public class MetadataContextSerializationWrapper { private readonly MetadataContextViewModel _viewModel; public MetadataContextSerializationWrapper(MetadataContextViewModel viewModel) { _viewModel = viewModel; } [JsonExtensionData] public Dictionary<string, JsonElement> ExtensionData { get { var dict = new Dictionary<string, JsonElement>(); foreach (var item in _viewModel.Items) { var json = JsonSerializer.SerializeToElement(new { id = item.Id, type = item.Type }); dict.Add(item.Name, json); } return dict; } } }
序列化时只需包装原ViewModel:
var wrapper = new MetadataContextSerializationWrapper(viewModel); var targetJson = JsonSerializer.Serialize(wrapper);
内容的提问来源于stack exchange,提问作者Lube
相关产品推荐
相关产品推荐

