Json.net deserialization null guid case

杀马特。学长 韩版系。学妹 提交于 2020-03-13 06:14:09

问题


I'm deserializing an object using Json.NET that contains a private field of type Guid and a public property for that field. When the value for my Guid is null in my json I want to assign Guid.Empty to my field.

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

But the deserializer wants to access the private field, cause I get this error when I try to deserialize:

Error converting value {null} to type 'System.Guid'. Path '[0].property', line 6, position 26.

How can I make it ignore the private field and use the public property instead?


回答1:


Json.NET refuses to set a null value for a Guid because it is a non-nullable value type. Try typing (Guid)null in the Immediate Window and you will see an error message indicating that this conversion cannot be made in .Net.

To work around this, you have a couple of options:

  1. Create a Guid? nullable proxy property. It can be private if you desire as long as it has a [JsonProperty] attribute:

    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. Create a JsonConverter that converts a null Json token to a default Guid value:

    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);
        }
    }
    

    Then apply it to your type as follows:

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

    Alternatively, you can apply the converter to all values of type T by adding the converter to JsonSerializerSettings.Converters. And, to register such a converter globally, see e.g. Registering a custom JsonConverter globally in Json.Net for a console app, How to set custom JsonSerializerSettings for Json.NET in MVC 4 Web API? for Web API, or Setting JsonConvert.DefaultSettings asp net core 2.0 not working as expected for ASP.NET Core.



来源:https://stackoverflow.com/questions/31747712/json-net-deserialization-null-guid-case

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!