Json.NET требует всех свойств при десериализации

В Json.NET, как мне сделать ВСЕ свойства, необходимые при десериализации? Я знаю, что могу делать это с атрибутами сообщений, но я не хочу этого делать. В основном потому, что для моей библиотеки сообщений потребуется внешняя зависимость.

Я попробовал параметр MissingMemberHandling.Error, но он делает противоположное тому, что я хочу. Я уверен, что у JSON есть дополнительные свойства. Я хочу, чтобы он потерпел неудачу, когда в JSON отсутствуют какие-либо свойства целевого объекта.

Я фактически десериализую к записям F #, и свойства вообще не могут быть нулевыми. (Они не могут быть присвоены нуль нормальными средствами в коде.) Но Json.NET с радостью по умолчанию присваивает свойствам null под обложками, когда данные отсутствуют.


версия принятого ответа F #

Резольвер

open System
open Newtonsoft.Json
open Newtonsoft.Json.Serialization

type RequireAllPropertiesContractResolver() =
    inherit DefaultContractResolver()

    override me.CreateObjectContract(objectType:Type) =
        let contract = base.CreateObjectContract(objectType)
        contract.ItemRequired <- new Nullable<Required>(Required.Always)
        contract

В настройках

let settings = new JsonSerializerSettings() // default settings
...
settings.ContractResolver <- new RequireAllPropertiesContractResolver()

Ответ 1

Добавьте атрибут [JsonObject(ItemRequired=Required.Always)] в ваши классы:

Тип: Требуется

Значение, указывающее, требуются ли свойства объекта.

Возможные значения для Required:

  • По умолчанию: свойство не требуется. Состояние по умолчанию.
  • AllowNull: свойство должно быть определено в JSON, но может иметь значение NULL.
  • Всегда: свойство должно быть определено в JSON и не может быть нулевым значением.
  • DisallowNull: свойство не является обязательным, но оно не может быть нулевым значением [если имеется]. (Json.NET 8.0.1 и более поздние версии.)

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

Обновить

Чтобы сделать это глобально для всех объектов, ItemRequired подкласс DefaultContractResolver и добавьте флаг ItemRequired ко всем объектным контрактам:

public class RequireObjectPropertiesContractResolver : DefaultContractResolver
{
    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);
        contract.ItemRequired = Required.Always;
        return contract;
    }
}

А потом позже, в настройках:

var settings = new JsonSerializerSettings { ContractResolver = new RequireObjectPropertiesContractResolver() };

Заметки:

Ответ 2

Я знаю, что я опаздываю на вечеринке здесь, но... Принимаются ответ заставляет все свойства должны быть доступны, что может быть не так хорошо для случая, когда ваша запись содержит типы параметров, сочетающие с NullValueHandling.Ignore параметром JsonSerializerSettings. В этом случае вам потребуется указать тип параметра, который слишком ограничен. Мы нашли, что это решение работает для нас:

type RequireAllPropertiesContractResolver() =
    inherit CamelCasePropertyNamesContractResolver()

    override __.CreateProperty(memb, serialization) =
        let prop = base.CreateProperty(memb, serialization)
        let isRequired = not (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() = typedefof<option<_>>)
        if isRequired then prop.Required <- Required.Always
        prop

Надеюсь, это кому-нибудь поможет.