JsonSerializer.Deserialize не удается - PullRequest
       9

JsonSerializer.Deserialize не удается

2 голосов
/ 08 февраля 2020

Рассмотрим код ...

using System;
using System.Text.Json;

public class Program
{
    public static void Main()
    {
        int id = 9;
        string str = "{\"id\": " + id + "}";
        var u = JsonSerializer.Deserialize<User>(str);
        Console.WriteLine($"User ID: {u.Id}, Correct: {id == u.Id}");  // always 0/init/default value
    }
}


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

Почему данные не десериализованы должным образом в объект User? Я также проверил поведение через DotNetFiddle на случай, если это проблема локальная для моей системы. Никаких исключений не выдается.

Моя фактическая реализация читается из действия [ApiController] [HttpPost] после I return Created("user", newUser). Он вызывается в моем проекте MVC / Razor через _httpClient.PostAsync. Я подтвердил, что значения верны, когда Created возвращается в вызов PostAsync, но, несмотря ни на что, значение, проанализированное из тела ответа, содержит только значения по умолчанию (фактический идентификатор - Guid).

Сначала я подумал, что это может быть проблема, связанная с UTF8, так как это кодировка для StringContent, которую я публикую на ApiController. Ссылка на десериализацию UTF8 здесь , но у меня возникли проблемы при переходе от IO.Stream HttpContent к ReadOnlySpan или Utf8JsonReader.

Я нашел этого проекта во время поиска, что заставляет меня думать, что оно должно работать так, как я ожидал.

Ответы [ 3 ]

2 голосов
/ 08 февраля 2020

Ваша проблема в том, что System.Text.Json чувствителен к регистру по умолчанию, поэтому "id": 9 (все строчные буквы) не сопоставлены со свойством Id. Из документов :

Соответствие свойств без учета регистра

По умолчанию при десериализации выполняется поиск совпадений имен свойств с учетом регистра между JSON и свойства целевого объекта. Чтобы изменить это поведение, установите JsonSerializerOptions.PropertyNameCaseInsensitive на true:

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
};
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options);

Так что вам нужно сделать это также:

var u = JsonSerializer.Deserialize<User>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

Демо fiddle # 1 здесь .

Вы можете настроить опцию при запуске в ASP. NET Core 3.0, как показано в Как установить json сериализатор настройки в asp. net core 3? :

services.AddControllers().AddJsonOptions(options =>
{
    options.PropertyNameCaseInsensitive = true;
});

В качестве альтернативы вы можете применить [JsonPropertyName("id")] к вашей модели:

public class User {
    [JsonPropertyName("id")]
    public int Id { get; set; }
}

Демонстрационная скрипка № 2 здесь .

1 голос
/ 08 февраля 2020

Благодаря mr5 , который предположил, что это проблема с оболочкой в ​​чате .

Изменение строки для использования TitleCase ("Id") решает проблему.

Я находился в процессе отправки тикета, и одна из возможно связанных проблем комментариев привела меня к другой проблеме , которая привела к документация, в которой есть решение

var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

Использование опций решает проблему ...

string str = "{\"id\": " + id + "}";
var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
var u = JsonSerializer.Deserialize<User>(str, options);

Оставьте все это на тот случай, если кому-то это поможет еще.

0 голосов
/ 21 апреля 2020

В ConfigureServices при Startup.cs

services.AddControllers()
        .AddJsonOptions(o =>{o.JsonSerializerOptions
        .PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        o.PropertyNameCasInsensitive = true
    }
);
...