c# - Json.net反序列化null guid案例

标签 c# json serialization json.net

我正在使用 Json.NET 反序列化一个对象,该对象包含一个 Guid 类型的私有(private)字段和该字段的一个公共(public)属性。当我的 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;
            }
        }
    }
}

但是反序列化器想要访问私有(private)字段,导致我在尝试反序列化时得到这个错误:

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

如何让它忽略私有(private)字段而使用公共(public)属性?

最佳答案

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

要解决这个问题,您有几个选择:

  1. 创建一个 Guid? 可为 null 的代理属性。如果您愿意,它可以是私有(private)的,只要它有 [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. 创建 JsonConverternull 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); // 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; }
    }
    

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

    如果您确实为控制台应用程序全局注册转换器,您可能需要为递归调用禁用它,如 JSON.Net throws StackOverflowException when using [JsonConvert()] 所示。 .

  3. 如果您只需要反序列化 Guid 的null 值而不是重新序列化它,您可以申请[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这将导致在序列化期间省略空的 Guid 值:

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

    请注意,如果 parameterized constructor在反序列化期间调用的具有同名的不可为 null 的 Guid 参数,可能需要不同的方法。

关于c# - Json.net反序列化null guid案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31747712/

相关文章:

asp.net - 从 ASMX 返回 JSON,并在 Javascript 中正确处理它

python - TypeError: 'NoneType' 类型的参数在 if 语句后不可迭代

c# - 第一次反序列化比后续反序列化花费的时间要长得多

c# - 如何从 IRedisClientsManager 获取低级原始字节 API?

c# - 字符串转二进制[]

c# - StyleCop 疯狂 : protected field

c# - 在调用函数 #1 时自动调用函数 #2

javascript - 使用 Javascript/jQuery 删除字符串中的反斜杠

java - 使用特定语法将Java对象转换为JSON

java - 序列化对象会包含元数据吗?