如何在序列化时忽略空值,而在反序列化时将其包括在内

时间:2019-06-18 21:58:34

标签: asp.net-web-api json.net

摘要

是否可以将Newtonsoft.Json.NullValueHandling.Ignore用于输出(序列化),而将NullValueHandling.Include用于输入(反序列化)?


详细信息

我正在使用ASP.NET Web API构建JSON API。我想从输出中删除不必要的null值,使用以下代码可以轻松做到这一点:

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

但是,在输入时,我想使用NullValueHandling.Include来包含空值,并在模型对象上触发该属性设置器。

为什么?

这些属性设置器如下所示:

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

其中MarkApplied记得Foo属性是显式设置的。这使我可以分辨出输入JSON对象之间的区别:

{ Foo: 123, Bar: "bar" }

我打算将Foo属性更新为123,并将Bar属性更新为"bar"

{ Foo: null, Bar: "bar" }

我打算将Foo属性更新为null,将Bar属性更新为"bar",并且

{ Bar: "bar" }

我打算将Bar属性更新为"bar",而不更改Foo属性的任何内容(与将其设置为null相对)。

>

什么不起作用

我已经将{{3}}作为一种选择。首先,我真的只希望这种行为适用于空值,而不希望具有有意义的默认值的数字和布尔值。另外,IncludeIgnore似乎与NullValueHandling的行为非常匹配,并且PopulateIgnoreAndPopulate选项不是我想要的,因为它们即使该属性未包含在输入JSON中,也会触发属性设置器。

1 个答案:

答案 0 :(得分:0)

好吧,所以我找到了this StackOverflow post,并且能够创建一个自定义的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();
        }
    }