Json.net反序列化null guid案例

时间:2015-07-31 13:44:04

标签: c# json serialization json.net

我正在使用包含Guid类型的私有字段和该字段的公共属性的Json.NET反序列化对象。当我的Guid的值在我的json中为空时,我想将Guid.Empty分配给我的字段。

public class MyClass
{
    private Guid property;
    public Guid Property
    {
        get { return property; }
        set 
        {
            if (value == null)
            {
                property = Guid.Empty;
            }
            else
            {
                property = value;
            }
        }
    }
}

但是deserializer想要访问私有字段,因为当我尝试反序列化时出现此错误:

  

将值{null}转换为类型'System.Guid'时出错。路径   '[0] .property',第6行,第26位。

如何让它忽略私有字段并改为使用公共属性?

1 个答案:

答案 0 :(得分:12)

Json.NET拒绝为null设置Guid值,因为它是一个不可为空的值类型。尝试在Immediate Window中输入(Guid)null,您会看到一条错误消息,指出无法在.Net中进行此转换。

要解决此问题,您可以选择以下几种方法:

  1. 创建Guid?可空代理属性。只要它具有[JsonProperty]属性,它就可以是私有的:

    public class MyClass
    {
        [JsonIgnore]
        public Guid Property { get; set; }
    
        [JsonProperty("Property")]
        Guid? NullableProperty { get { return Property == Guid.Empty ? null : (Guid?)Property; } set { Property = (value == null ? Guid.Empty : value.Value); } }
    }
    
  2. 创建JsonConverter,将null Json令牌转换为默认Guid值:

    public class NullToDefaultConverter<T> : JsonConverter where T : struct
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(T);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var token = JToken.Load(reader);
            if (token == null || token.Type == JTokenType.Null)
                return default(T);
            return token.ToObject(objectType);
        }
    
        // Return false instead if you don't want default values to be written as null
        public override bool CanWrite { get { return true; } }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (EqualityComparer<T>.Default.Equals((T)value, default(T)))
                writer.WriteNull();
            else
                writer.WriteValue(value);
        }
    }
    

    然后将其应用于您的类型,如下所示:

    public class MyClass
    {
        [JsonConverter(typeof(NullToDefaultConverter<Guid>))]
        public Guid Property { get; set; }
    }
    

    或者,您可以将转换器添加到JsonSerializerSettings.Converters,将转换器应用于T类型的所有值。并且,要在全球注册这样的转换器,请参阅例如用于控制台应用的 Registering a custom JsonConverter globally in Json.Net ,用于Web API的 How to set custom JsonSerializerSettings for Json.NET in MVC 4 Web API? 或用于ASP.NET的 Setting JsonConvert.DefaultSettings asp net core 2.0 not working as expected