C# .Net5中如何让Newtonsoft对同一模型按不同格式序列化?
问题优化方案
以下方案均基于C# .NET 5环境实现,你可以根据自己的场景选择:
方案1:自定义构造/转换方法(无需第三方依赖)
不需要额外引入库,直接在目标模型内实现转换逻辑,统一管理赋值规则,避免到处写重复的for循环。
注:以下代码假设你的
TypeModel中存储值的属性名为Value,请自行替换为你实际的属性名。
CollectionOptionDownloadModel转换实现
public class CollectionOptionDownloadModel { // 原有属性保持不变 public string sport { get; set; } public string plan { get; set; } public int fromDay { get; set; } public int fromMonth { get; set; } public int fromYear { get; set; } public int toDay { get; set; } public int toMonth { get; set; } public int toYear { get; set; } public int? eventId { get; set; } public string eventName { get; set; } public List<string> marketTypesCollection { get; set; } public List<string> countriesCollection { get; set; } public List<string> fileTypeCollection { get; set; } // 新增构造方法,直接传入源模型完成赋值 public CollectionOptionDownloadModel(CollectionOptionModel source) { // 基础属性直接拷贝 sport = source.sport; plan = source.plan; fromDay = source.fromDay; fromMonth = source.fromMonth; fromYear = source.fromYear; toDay = source.toDay; toMonth = source.toMonth; toYear = source.toYear; eventId = source.eventId; eventName = source.eventName; // 集合用Linq直接转换,自动判空避免空引用异常 marketTypesCollection = source.marketTypesCollection?.Select(t => t.Value).ToList(); countriesCollection = source.countriesCollection?.Select(t => t.Value).ToList(); fileTypeCollection = source.fileTypeCollection?.Select(t => t.Value).ToList(); } }
SingleOptionResultsModel转换实现
public class SingleOptionResultsModel { // 原有属性保持不变 public string sport { get; set; } public string plan { get; set; } public int fromDay { get; set; } public int fromMonth { get; set; } public int fromYear { get; set; } public int toDay { get; set; } public int toMonth { get; set; } public int toYear { get; set; } public int? eventId { get; set; } public string eventName { get; set; } public string marketTypesCollection { get; set; } public string countriesCollection { get; set; } public string fileTypeCollection { get; set; } public List<string> fileList { get; set; } // 新增构造方法,支持同时传入文件列表 public SingleOptionResultsModel(CollectionOptionModel source, List<string> fileList = null) { sport = source.sport; plan = source.plan; fromDay = source.fromDay; fromMonth = source.fromMonth; fromYear = source.fromYear; toDay = source.toDay; toMonth = source.toMonth; toYear = source.toYear; eventId = source.eventId; eventName = source.eventName; // 集合直接拼接为逗号分隔字符串,自动处理空集合 marketTypesCollection = string.Join(",", source.marketTypesCollection?.Select(t => t.Value) ?? Enumerable.Empty<string>()); countriesCollection = string.Join(",", source.countriesCollection?.Select(t => t.Value) ?? Enumerable.Empty<string>()); fileTypeCollection = string.Join(",", source.fileTypeCollection?.Select(t => t.Value) ?? Enumerable.Empty<string>()); this.fileList = fileList; } }
使用示例
// 你的原始模型对象 var sourceModel = new CollectionOptionModel(); // 一行完成API调用模型转换 var downloadModel = new CollectionOptionDownloadModel(sourceModel); // 一行完成结果模型转换,可直接传入API返回的文件列表 var resultModel = new SingleOptionResultsModel(sourceModel, apiReturnFileList);
方案2:AutoMapper映射(适合大量同类转换场景)
如果你后续有非常多类似的模型转换需求,推荐使用AutoMapper库,一次配置全局可用,不需要重复写赋值代码。
- 先通过NuGet安装
AutoMapper和AutoMapper.Extensions.Microsoft.DependencyInjection(依赖注入场景使用) - 全局配置映射规则:
var mapperConfig = new MapperConfiguration(cfg => { // 配置CollectionOptionModel转CollectionOptionDownloadModel规则 cfg.CreateMap<CollectionOptionModel, CollectionOptionDownloadModel>() .ForMember(dest => dest.marketTypesCollection, opt => opt.MapFrom(src => src.marketTypesCollection.Select(t => t.Value).ToList())) .ForMember(dest => dest.countriesCollection, opt => opt.MapFrom(src => src.countriesCollection.Select(t => t.Value).ToList())) .ForMember(dest => dest.fileTypeCollection, opt => opt.MapFrom(src => src.fileTypeCollection.Select(t => t.Value).ToList())); // 配置CollectionOptionModel转SingleOptionResultsModel规则 cfg.CreateMap<CollectionOptionModel, SingleOptionResultsModel>() .ForMember(dest => dest.marketTypesCollection, opt => opt.MapFrom(src => string.Join(",", src.marketTypesCollection.Select(t => t.Value)))) .ForMember(dest => dest.countriesCollection, opt => opt.MapFrom(src => string.Join(",", src.countriesCollection.Select(t => t.Value)))) .ForMember(dest => dest.fileTypeCollection, opt => opt.MapFrom(src => string.Join(",", src.fileTypeCollection.Select(t => t.Value)))); }); var mapper = mapperConfig.CreateMapper();
- 转换调用:
var downloadModel = mapper.Map<CollectionOptionDownloadModel>(sourceModel); var resultModel = mapper.Map<SingleOptionResultsModel>(sourceModel); // 赋值文件列表 resultModel.fileList = apiReturnFileList;
可选:自定义Getter方案
如果你只需要序列化转换,不需要修改目标模型的属性值,可以用自定义Getter实现,但是这种方案不适合需要修改属性的场景:
public class CollectionOptionDownloadModel { // 直接挂载源模型 public CollectionOptionModel Source { get; set; } // 所有属性通过Getter读取源模型的值 public string sport => Source?.sport; public List<string> marketTypesCollection => Source?.marketTypesCollection?.Select(t => t.Value).ToList(); // 其他属性以此类推 }
内容的提问来源于stack exchange,提问作者davezeetone
相关产品推荐
相关产品推荐

