.Net Core 3 Десериализующий список объектов создает «пустые» объекты

#c# #asp.net-core #asp.net-core-3.1 #json-deserialization

#c# #asp.net-core #asp.net-core-3.1 #json-десериализация

Вопрос:

В моем веб-приложении .Net Core 3.1 у меня есть класс, разделяемый серверной частью и интерфейсом, который выглядит следующим образом

 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.

Json, который получает HttpClient, выглядит следующим образом:

 [
    {
        "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());
 

Из этого я получаю правильное количество объектов в списке, но все они имеют значения 0 или null и т.д.
Что я делаю не так?

Раньше я использовал ReadAsAsync(), который работал нормально, но устарел.Net core 3

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

Комментарии:

1. Вы проверили запрос, который вы запускаете, имеет ли Order.Products значение? Я имею в виду, соответствует ли ваш запрос Include отображенным объектам там? Верны ли ваши данные, я имею в виду, должны ли там быть данные?

2. Продукты в базе данных равны нулю, все в порядке. Но, например, идентификатор для всех объектов равен 0, чего нет в Json

3. Поэтому, если вам нужно другое значение по умолчанию Order.Products , отличное от null, когда в базе данных нет данных, я бы инициировал Order.Products field int он конструктор. В результате это будет список с нулевым элементом. Это то, что вы ищете?

4. Я думаю, вы, возможно, неправильно поняли мою проблему здесь. Объект, который я получаю в результате десериализации, отличается от объекта в Json и Db. И это относится к объекту или порядку, а не к конкретному порядку. Продукты

5. Вам нужно убедиться, что написание ваших свойств такое же, как в файле json. Если вы хотите использовать другое написание, вам нужно использовать атрибуты, чтобы указать десериализатору json, какое свойство является полем в json

Ответ №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);
 

Комментарии:

1. Ну, у меня один и тот же класс для интерфейса и серверной части, и оба они используют один и тот же сериализатор в System.Text.Json. Если я использую NewtonsoftJson, который используется Microsoft. AspNet. WebAPI.Client работает нормально. Я не вижу причин, по которым он не десериализовался бы с помощью System.Text. Json, когда он был сериализован с ним.

2. Я понял вашу точку зрения, и вы совершенно правы. Однако суть, которую я пытаюсь подчеркнуть, заключается в том, как другой десериализатор обрабатывает синтаксический анализ JSON. Я столкнулся с такой же, хотя и похожей проблемой год назад, и решил ее, переключив мой анализатор JSON. @Snackerino