Как игнорировать нулевые значения при сериализации, но включать их при десериализации - PullRequest
0 голосов
/ 19 июня 2019

Резюме

Можно ли использовать Newtonsoft.Json.NullValueHandling.Ignore для вывода (сериализация), но использовать NullValueHandling.Include для ввода (десериализация)?


Подробнее

Я создаю JSON API, используя ASP.NET Web API. Я хочу удалить ненужные нулевые значения из вывода, что легко сделать с помощью следующего кода:

config.Formatters.JsonFormatter.SerializerSettings =
    new Newtonsoft.Json.JsonSerializerSettings {
        NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
    };

Однако при вводе я хочу использовать NullValueHandling.Include для включения значений NULL и установки этих триггеров свойств на объектах моей модели.

Почему?

Эти установщики свойств выглядят следующим образом:

public long? Foo
{
    get { return _Foo; }
    set { _Foo = MarkApplied(nameof(Foo), value); }
}

, где MarkApplied помнит, что свойство Foo было установлено Explicity. Это позволяет мне определить разницу между входным объектом JSON:

{ Foo: 123, Bar: "bar" }

, который намеревается обновить свойство Foo до 123 и свойство Bar до "bar",

{ Foo: null, Bar: "bar" }

, который намеревается обновить свойство Foo до null и свойство Bar до "bar" и

{ Bar: "bar" }

, который намеревается обновить свойство Bar до "bar" и ничего не менять в свойстве Foo (в отличие от установки null).

Что не будет работать

Я уже рассматривал DefaultValueHandling как вариант. С одной стороны, я действительно хочу это поведение только для нулевых значений, а не для чисел и логических значений, которые имеют значимые значения по умолчанию. Кроме того, Include и Ignore, кажется, в значительной степени соответствуют поведению NullValueHandling, а параметры Populate и IgnoreAndPopulate не то, что мне нужно, потому что они будут вызывать установщики свойств, даже когда свойство не установлено. не включен во входной JSON.

1 Ответ

0 голосов
/ 20 июня 2019

Хорошо, поэтому я нашел это сообщение StackOverflow и смог создать собственный JsonConverter, который выполняет свою работу:

    public class V2JsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType.IsSubclassOf(typeof(ApiModelBase));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jsonObj = JObject.Load(reader);
            var targetObj = (ApiModelBase)Activator.CreateInstance(objectType);

            foreach (var prop in objectType.GetProperties().Where(p => p.CanWrite))
            {
                JToken value;
                if (jsonObj.TryGetValue(prop.Name, StringComparison.OrdinalIgnoreCase, out value))
                {
                    prop.SetValue(targetObj, value.ToObject(prop.PropertyType, serializer));
                }
            }

            return targetObj;
        }

        public override bool CanWrite => false;

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...