小编典典

Json.net反序列化null gui案例

json

我正在反序列化使用的对象Json.NET,该对象包含Guid类型的私有字段和该字段的公共属性。当Guid我的json中的my的值为null时,我想分配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]。属性”,第6行,位置26。

如何使其忽略私有字段,而使用公共属性?


阅读 326

收藏
2020-07-27

共1个答案

小编典典

Json.NET拒绝null为a
设置值,Guid因为它是非空值类型。尝试(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); } }
    }
  1. 创建一个JsonConverternullJson令牌转换为默认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); // Deserialize using default serializer
        }

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

或者,您可以T通过将转换器添加到来将转换器应用于所有类型的值JsonSerializerSettings.Converters。并且,要在全球范围内注册这样的转换器,请参见例如,
如何在MVC 4 WebAPI中为Json.NET设置自定义JsonSerializerSettings?]
对于Web API, [设置JsonConvert.DefaultSettings as net net2.0无法 ASP.NET Core的
预期运行 ,或者_在Json.Net中_ 为控制台应用程序_全局注册了自定义JsonConverter_ 。

如果确实为控制台应用程序全局注册了转换器,则可能需要禁用它以进行递归调用,如
JSON中 所示。使用[JsonConvert()]时]Net会引发

  1. 如果只需要 null序列化Guid 的值而不必重新序列化,则可以将其应用于[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]Guid属性,null尽管这些值是无效的Guid值,但这些值将被忽略:
    public class MyClass
    

    {
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public Guid Property { get; set; }
    }

当然,如果您这样做,您的Guid将会重新序列化为"00000000-0000-0000-0000-000000000000"。为了改善这种情况,您可以应用[`DefaultValueHandling

DefaultValueHandling.Ignore`](https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonPropertyAttribute_DefaultValueHandling.htm)它,这将导致在序列化期间忽略空的Guid值:

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
public Guid Property { get; set; }

请注意,如果在反序列化期间调用的参数化构造函数具有相同名称的不可为空的Guid参数,则可能需要其他方法。

2020-07-27