【问题标题】:.Net Core 3 Deserializing List of object creates "empty" objects.Net Core 3反序列化对象列表创建“空”对象
【发布时间】:2021-01-29 12:10:15
【问题描述】:

在我的 .Net Core 3.1 Web 应用程序中,我有一个后端和前端共享的类,如下所示

public class Order
{
    [Key]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public DateTime OrderTime { get; set; }
    public int UserId { get; set; }
    public int Vat { get; set; }
    [NotMapped]
    public Dictionary<string, int> Products { get; set; }
    public int Discount { get; set; }
    public float ShippingPrice { get; set; }
    public bool Shipped { get; set; }
    public bool Cancelled { get; set; }
    public string CancelReason { get; set; }

    public Order()
    {

    }
}

在前端,我使用 HttpClient 从 REST API 获取订单列表。

httpClient 接收到的 Json 如下所示:

[
    {
        "id": 1,
        "orderTime": "2021-01-28T14:55:03.077",
        "userId": 0,
        "vat": 0,
        "products": null,
        "discount": 0,
        "shippingPrice": 0,
        "shipped": true,
        "cancelled": true,
        "cancelReason": "string"
    },
    {
        "id": 2,
        "orderTime": "2021-01-28T14:55:03.077",
        "userId": 2,
        "vat": 0,
        "products": null,
        "discount": 10,
        "shippingPrice": 0,
        "shipped": false,
        "cancelled": false,
        "cancelReason": null
    }
]

对于反序列化,我使用的是 JsonSerializer:

var returnOrders = await JsonSerializer.DeserializeAsync<List<Order>>(await response.Content.ReadAsStreamAsync());

从中我确实得到了 List 上正确数量的对象,但它们都具有 0 或 null 等值。 我做错了什么?

在我使用 ReadAsAsync() 之前,它运行良好,但在 .Net core 3 中已弃用

await response.Content.ReadAsAsync<List<Object>>();

【问题讨论】:

  • 您是否检查过您触发的查询 Order.Products 是否有价值?我的意思是您的查询Includes 是否映射了那里的实体?您的数据是否正确,我的意思是那里应该有数据?
  • 数据库中的产品为空,这样做很好。但是例如所有对象的ID都是0,而Json中不是这样
  • 因此,如果您希望在数据库中没有数据时 Order.Products 的默认值与 null 不同,那么我将在构造函数中启动 Order.Products 字段。结果,它将是一个具有零元素的列表。这是你要找的吗?
  • 我想你可能误解了我的问题。我从反序列化中得到的对象与 Json 和 Db 中的对象不同。它适用于对象或订单,而不是专门的 Order.Products
  • 您需要确保属性的拼写与 json 文件中的拼写相同。如果你想使用不同的拼写,那么你必须使用属性来告诉json反序列化器哪个属性是json中的哪个字段

标签: c# asp.net-core asp.net-core-3.1 json-deserialization


【解决方案1】:

默认情况下,JsonSerializer 在 json 中查找与您的类中定义的名称相同的属性。在您的情况下,您使用的是 CamelCase 命名约定,因此您需要像这样指定它:

var options = new JsonSerializerOptions()
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var returnOrders = await JsonSerializer.DeserializeAsync<List<Order>>(await response.Content.ReadAsStreamAsync(), options);

【讨论】:

    【解决方案2】:

    这可能是由于不同的反序列化器使用 JSON 反序列化约定而发生的。例如,有时 JSON 键的大小写很重要。

    尝试使用 NewtonsoftJSON 反序列化器,而不是您使用的默认反序列化器。它会在不检查大小写的情况下解析 JSON。

    string json = @"{
    'Email': 'james@example.com',
    'Active': true,
    'CreatedDate': '2013-01-20T00:00:00Z',
    'Roles': [ 'User', 'Admin' ]
    }";
    
    Account account = JsonConvert.DeserializeObject<Account>(json);
    Console.WriteLine(account.Email);
    

    【讨论】:

    • 嗯,我有相同的前端和后端类,它们都在 System.Text.Json 中使用相同的序列化程序。如果我使用 Microsoft.AspNet.WebApi.Client 使用的 NewtonsoftJson,它可以正常工作。我看不出为什么它在用它序列化时不会用 System.Text.Json 反序列化。
    • 我明白你的意思,你是完全正确的。然而,我试图说明的是不同的反序列化器处理 JSON 解析的方式。一年前我遇到了不同的问题,尽管类似的问题并通过切换我的 JSON 解析器来解决。 @Snackerino
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多