如何在Json.NET中将缺少的属性反序列化为默认值?

时间:2014-12-17 22:15:34

标签: json.net

我有一个用DataContract和DataMember属性注释的类。有些成员被标记为DataMember(IsRequired = true)。当我从Json.NET通过线路序列化实例,并且所需的对象成员具有null值时,它们的序列化值在输出中丢失(这显然相当于在JSON中为null)。我没关系。

我创造了一种" echo"返回作为响应发送给它的数据的服务。所以这个服务接收带有缺少成员的JSON(或者根据你看它的方式为null成员),然后将它发送回我的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
}

2 个答案:

答案 0 :(得分:3)

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

  1. 您可以使用[JsonProperty(Required = Required.Default)]标记相同的属性。这是有效的,因为[JsonProperty]优先于Json.Net中的[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();
    

答案 1 :(得分:0)

这看起来像是我的代码中的一个真正的疣,并且需要为每个可空的但必需的成员重复,但是它起作用,并且似乎增加了可忽略的开销。我在原始代码段中的try块之前添加了这个:

JToken maybeHasIt = null;
if (!json.TryGetValue("IAmRequired", StringComparison.InvariantCultureIgnoreCase, out maybeHasIt))
{
    json.Add("IAmRequired", null);
}