Один ключевой сценарий все еще не охвачен новыми API.

Когда я услышал о новых API-интерфейсах System.Text.Json, я был заинтригован. Я большой поклонник Newtonsoft.Json, но улучшения в Pipes в .NET Core 2.2 означают, что может появиться возможность неплохого прироста производительности.

Я был очень рад, что Microsoft решила провести исследование удобства использования своих новых API-интерфейсов, чтобы убедиться, что они не слишком сложны в использовании. Оказывается, были. Итак, в Preview 8 команда проделала кучу работ по очистке API-интерфейсов, сделав их более предсказуемыми (AKA соответствует тому, к чему люди привыкли, с Newtonsoft.Json).

Изменения велики, а новая поверхность API чиста и предсказуема. Но когда я пошел обновлять Azure DevOps Buddy до Preview 8, я столкнулся с некоторыми проблемами, связанными с ключевым сценарием.

Связывание модели в MVC / WebApi довольно раздражает, поскольку следующий код не работает, когда вы отправляете POST объект JSON в API.

public async Task<bool> SomeMethod([FromBody] SomeObject data){
}

для того, чтобы это сработало, вы должны создать объект для POST следующим образом:

var request = new { 
    data: { 
        property1: "test1",
        property2: "test2"
    }
};
var result = $ajax.post("someurl", request);

Мне не очень нравится заставлять конечного разработчика называть объект таким образом, поэтому я часто использую вместо этого такой шаблон:

public async Task<bool> SomeMethod([FromBody] JObject data)
{
    var model = data.ToObject<SomeObject>();
}

Насколько я могу судить (и я могу ошибаться в этом, поэтому, пожалуйста, дайте мне знать, если я прав, и я обновлю сообщение), в System.Text.Json нет эквивалента JObject. JsonDocument не имеет пустого конструктора, поэтому его нельзя использовать во время привязки модели. Я полагаю, что можно было бы создать индивидуальную подшивку модели, но усилия не окупились.

К счастью, API-интерфейсы не исключают друг друга, вы можете использовать ОБА в своем приложении, если вы добавите NuGet-пакет Microsoft.AspNetCore.Mvc.NewtonsoftJson в свой проект, а затем зарегистрируете их в Startup.cs следующим образом:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddNewtonsoftJson(options => 
            options.SerializerSettings.ContractResolver = new 
            CamelCasePropertyNamesContractResolver())
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNameCaseInsensitive = true);

Тогда желаемый узор продолжит работу.

Вот и все! Если найду схему получше, обязательно обновлю этот пост. Удачного кодирования!