将字符串值反序列化为 ienumerable<t> in asp.net core 3

Deserialize string values to ienumerable<t> in asp.net core 3

我想将此 json 数据反序列化为 Result class 并将 3 个图书值(FirstBook、SecondBook、ThirdBook)放入 IEnumerable<书>:

[
  {      
    "Id": 1,
    "FirstBook": "B1",
    "SecondBook": "B2",
    "ThirdBook": "B3",
    ...    
  },
  {
    "Id": 2,
    "FirstBook": "BB1",
    "SecondBook": "BB2",
    "ThirdBook": "BB3",
    ...
  }
]

结果Class:

public class Result
{
  public int Id { get; set;}

  [JsonConverter(typeof(BooksJsonConverter))]
  public IEnumerable<Book> Books { get; set; }
}

图书class:

public class Book
{
    public string Name { get; set; }
}

反序列化为 class Result 包含 IEnumerable< Book >

JsonConvert.DeserializeObject<IEnumerable<Result>>(json);

我想我应该创建 JsonConverter:

public class BooksJsonConverter : JsonConverter<IEnumerable<Book>>
{
    public override IEnumerable<Book> ReadJson(JsonReader reader, Type objectType, IEnumerable<Book> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        //What should i write here?
        return new List<Book>();
    }

    public override void WriteJson(JsonWriter writer, Book value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

在这种情况下,BooksJsonConverter 的 ReadJson 没有被调用,但是当我添加 JsonProperty attrib 时它被调用了,但是我不知道我应该在 ReadJson 里面写什么:

public class Result
{
  public int Id { get; set;}

  [JsonConverter(typeof(BooksJsonConverter))]
  [JsonProperty("FirstBook")]
  public IEnumerable<Book> Books { get; set; }
}

问题是我应该如何将 FirstBook、SecondBook、ThirdBook 从 json 转换为结果 class 中的 IEnumerable< Book >?

由于您没有提供 Book class 结构,我将其自定义为包含一个 BookName 字段,如下所示。

   public class Book
    {
        public string BookName { get; set; }
    }



[JsonConverter(typeof(CustomeJsonConverter))]
public class Result
{
    public int Id { get; set; }
    public IEnumerable<Book> Books { get; set; }
}

更新

好的,jsonconverter可以实现,方法大致相同,但是需要在Result class而不是Book中添加自定义的jsonconverter属性,其中Book class 将被转换并添加到结果中。

代码如下:

 public class HomeController : Controller
    {
        public IActionResult Test()
        {
            string json = @" [
    {
      'Id': 1,
      'FirstBook': 'B1',
      'SecondBook': 'B2',
      'ThirdBook': 'B3'
    },
    {
      'Id': 2,
      'FirstBook': 'BB1',
      'SecondBook': 'BB2',
      'ThirdBook': 'BB3'
    }
  ] ";
            var xx = JsonConvert.DeserializeObject<IEnumerable<Result>>(json,new CustomeJsonConverter());
            return Ok();
        }

    }


public class CustomeJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return System.Attribute.GetCustomAttributes(objectType).Any(v => v is KnownTypeAttribute);
        }
        public override bool CanWrite
        {
            get { return false; }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        { 
            // Load JObject from stream
            JObject jObject = JObject.Load(reader);
            Result result = new Result();
            Dictionary<string, string> dictObj = jObject.ToObject<Dictionary<string, string>>();
            List<Book> books = new List<Book>();
            foreach (var obj in dictObj)
            {
                if (obj.Key.Contains("Book"))
                {
                    Book book = new Book()
                    {
                        Name = obj.Value
                    };
                    books.Add(book);
                }
            }
            result.Id = Convert.ToInt32(dictObj["Id"]);
            result.Books = books.AsEnumerable();
            return result; 
        }


        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

    }

也可以参考this.

您可以使用 JsonExtensionData 来序列化目标对象上没有匹配属性的 JSON 文档的元素:

 public class Result
    {
        public int Id { get; set; }

        public IEnumerable<Book> Books { get; set; }

        [JsonExtensionData]
        private IDictionary<string, JToken> _extensionData;

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            Books = _extensionData
             .Where(d => d.Key.Equals("FirstBook") || d.Key.Equals("SecondBook"))
             .Select(b => new Book { Name = b.Value.ToString() });
        }
    }