如何在Json.NET中将缺少的属性反序列化为默认值? [英] How do I deserialize a missing property to a default value in Json.NET?

查看:189
本文介绍了如何在Json.NET中将缺少的属性反序列化为默认值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用DataContract和DataMember属性注释的类.有些成员被标记为DataMember(IsRequired = true).当我通过Json.NET的网络对实例进行序列化,并且所需的对象成员具有null值时,则其序列化的值在输出中丢失(这显然等效于JSON中的null).我可以.

我创建了一种回显"服务,该服务返回发送给它的数据作为响应.因此,此服务接收到缺少成员(或空成员,具体取决于您的外观)的JSON,然后将其立即发送回我的Json.NET客户端.通过Fiddler(代理嗅探器)查看时,导线上的JSON在两个方向上看起来都是相同的.到目前为止一切顺利.

当原始Json.NET发送者接收到要反序列化的JSON响应时,序列化程序将引发有关在JSON有效负载中找不到所需成员的异常:

Required property 'IAmRequired' not found in JSON. Path ''.

这是不幸的,因为序列化程序因此无法反序列化先前已序列化的数据而没有问题.

更改DataContract类以使不需要成员(出于多种原因,我不想这样做)的简短方法,是否有办法使Json.NET将缺少的成员反序列化为默认值(例如null)? /p>

这是我的反序列化代码:

HasRequired h = null;
JObject json = response as JObject; // hand waving here
try
{
    JsonSerializer ser = new JsonSerializer();
    ser.MissingMemberHandling = MissingMemberHandling.Ignore; // doesn't seem to help
    ser.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; // doesn't seem to help
    ser.NullValueHandling = NullValueHandling.Include; // doesn't seem to help
    h = json.ToObject<HasRequired>(ser);
}
catch (Exception ex)
{
    // bummer, missing required members still
}

解决方案

如果您具有标记为[DataMember(Required = true)]的属性,并且想要覆盖所需的行为,则可以执行以下几项操作:

  1. 您可以使用[JsonProperty(Required = Required.Default)]标记这些相同的属性.之所以可行,是因为在Json.Net中[JsonProperty]优先于[DataMember].

    [DataContract]
    public class HasRequired
    {
        [DataMember(Required = true)]
        [JsonProperty(Required = Required.Default)]
        public string IAmRequired { get; set; }
    }
    

  2. 或者,您可以创建一个自定义ContractResolver,以编程方式在每个属性上设置Required = Required.Default.

    class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);
            prop.Required = Required.Default;
            return prop;
        }
    }
    

    要使用解析器,只需将序列化程序上的ContractResolver属性设置为自定义解析器的新实例:

    JsonSerializer ser = new JsonSerializer();
    ser = new CustomResolver();
    

I have a class that is annotated with DataContract and DataMember attributes. Some members are marked as DataMember(IsRequired = true). When I serialize instances over the wire from Json.NET, and the required object members have null value, then their serialized values are missing in the output (which is apparently equivalent to being null in JSON). I'm okay with that.

I've created a sort of "echo" service which returns data sent to it as a response. So this service receives the JSON with missing members (or null members depending on how you look at it), and then sends it right back to my Json.NET client. The JSON on the wire looks the same in both directions as viewed through Fiddler (a proxy sniffer). So far so good.

When the original Json.NET sender receives the JSON response to deserialize it, the serializer throws an exception about not finding required members in the JSON payload:

Required property 'IAmRequired' not found in JSON. Path ''.

That is unfortunate, as the serializer is thus not able to deserialize data that it had previously serialized without a problem.

Short of changing the DataContract class to make the member not required (which I do not want to do for a number of reasons), is there a way to make Json.NET deserialize missing members to default values such as null?

Here is my deserialization code:

HasRequired h = null;
JObject json = response as JObject; // hand waving here
try
{
    JsonSerializer ser = new JsonSerializer();
    ser.MissingMemberHandling = MissingMemberHandling.Ignore; // doesn't seem to help
    ser.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; // doesn't seem to help
    ser.NullValueHandling = NullValueHandling.Include; // doesn't seem to help
    h = json.ToObject<HasRequired>(ser);
}
catch (Exception ex)
{
    // bummer, missing required members still
}

解决方案

If you have properties marked with [DataMember(Required = true)] and you want to override the required behavior, there are a couple of things you can do:

  1. You can mark those same properties with [JsonProperty(Required = Required.Default)]. This works because [JsonProperty] takes precedence over [DataMember] in Json.Net.

    [DataContract]
    public class HasRequired
    {
        [DataMember(Required = true)]
        [JsonProperty(Required = Required.Default)]
        public string IAmRequired { get; set; }
    }
    

  2. Or, you can create a custom ContractResolver that programmatically sets Required = Required.Default on every property.

    class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);
            prop.Required = Required.Default;
            return prop;
        }
    }
    

    To use the resolver, simply set the ContractResolver property on the serializer to a new instance of the custom resolver:

    JsonSerializer ser = new JsonSerializer();
    ser = new CustomResolver();
    

这篇关于如何在Json.NET中将缺少的属性反序列化为默认值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆