ASP.NET Core中如何将JSON多字段反序列化为IEnumerable<Book>
解决JSON多字段转IEnumerable集合的反序列化问题
我明白你遇到的问题了:一开始自定义的BooksJsonConverter没被触发,加了[JsonProperty("FirstBook")]虽然能调用转换器,但又不知道怎么处理多个字段转集合。让我一步步帮你解决这个问题:
核心问题分析
你最初的转换器没被调用,原因很简单:Json.NET只会在JSON中存在对应属性键的时候,才会触发该属性的转换器。你的Result类里的Books属性在JSON里没有对应的"Books"字段,所以转换器根本不会被执行。而添加[JsonProperty("FirstBook")]后,Json.NET会把"FirstBook"的值传给转换器,但这只是单个字段,不是我们需要的多字段集合。
正确解决方案:给Result类使用自定义转换器
更合适的做法是给整个Result类添加自定义转换器,这样我们可以在序列化/反序列化时手动处理所有相关字段,把FirstBook、SecondBook、ThirdBook收集成IEnumerable<Book>集合。
步骤1:编写Result类的自定义转换器
public class ResultJsonConverter : JsonConverter<Result> { // 反序列化逻辑:把JSON中的多Book字段转成集合 public override Result ReadJson(JsonReader reader, Type objectType, Result existingValue, bool hasExistingValue, JsonSerializer serializer) { // 加载整个Result对应的JSON对象 var jObject = JObject.Load(reader); var result = new Result { // 读取Id字段 Id = jObject.GetValue("Id").ToObject<int>(serializer), Books = new List<Book>() }; // 定义需要收集的Book字段列表 var bookFieldNames = new[] { "FirstBook", "SecondBook", "ThirdBook" }; foreach (var fieldName in bookFieldNames) { // 读取字段值,跳过空值 var bookName = jObject[fieldName]?.ToString(); if (!string.IsNullOrWhiteSpace(bookName)) { result.Books.Add(new Book { Name = bookName }); } } return result; } // 可选:如果需要把Result序列化为原始JSON格式,实现WriteJson方法 public override void WriteJson(JsonWriter writer, Result value, JsonSerializer serializer) { var jObject = new JObject(); jObject.Add("Id", value.Id); var booksList = value.Books?.ToList(); if (booksList != null) { if (booksList.Count > 0) jObject.Add("FirstBook", booksList[0].Name); if (booksList.Count > 1) jObject.Add("SecondBook", booksList[1].Name); if (booksList.Count > 2) jObject.Add("ThirdBook", booksList[2].Name); } jObject.WriteTo(writer); } }
步骤2:给Result类添加转换器属性
修改你的Result类,加上[JsonConverter]属性:
[JsonConverter(typeof(ResultJsonConverter))] public class Result { public int Id { get; set;} public IEnumerable<Book> Books { get; set; } }
步骤3:正常执行反序列化
现在你可以直接调用原来的反序列化代码,转换器会自动触发:
var results = JsonConvert.DeserializeObject<IEnumerable<Result>>(json);
额外说明
如果你不想给整个类加转换器,也可以通过自定义ContractResolver来实现字段映射,但类级别的转换器逻辑更直观,容易维护。另外,上面的代码还包含了序列化的逻辑,如果你的场景不需要序列化,可以去掉WriteJson方法,同时重写CanWrite属性返回false。
内容的提问来源于stack exchange,提问作者Noob
相关产品推荐
相关产品推荐

