Json.net 反序列化 null guid 案例

时间:2023-04-25
本文介绍了Json.net 反序列化 null guid 案例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

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

但是 deserializer 想要访问私有字段,导致我在尝试反序列化时收到此错误:

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

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

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?

推荐答案

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

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. 创建一个 Guid? 可为空的代理属性.如果您愿意,它可以是私有的,只要它具有 [JsonProperty] 属性:

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

  • 创建一个 JsonConverternull Json 令牌转换为默认 Guid 值:

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

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

    Then apply it to your type as follows:

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

    或者,您可以通过将转换器添加到 T 类型的所有值.htm" rel="noreferrer">JsonSerializerSettings.Converters.而且,要在全球范围内注册这样的转换器,请参阅例如如何在 MVC 4 Web API 中为 Json.NET 设置自定义 JsonSerializerSettings? 用于 Web API,设置 JsonConvert.DefaultSettings asp net core 2.0 无法正常工作 用于 ASP.NET Core 或 在 Json.Net 中全局注册自定义 JsonConverter对于控制台应用程序.

    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.How to set custom JsonSerializerSettings for Json.NET in MVC 4 Web API? for Web API, Setting JsonConvert.DefaultSettings asp net core 2.0 not working as expected for ASP.NET Core or Registering a custom JsonConverter globally in Json.Net for a console app.

    如果您为控制台应用程序全局注册转换器,您可能需要禁用它以进行递归调用,如 JSON.Net 在使用 [JsonConvert()] 时抛出 StackOverflowException.

    If you do register the converter globally for a console app, you may need to disable it for recursive calls as shown in JSON.Net throws StackOverflowException when using [JsonConvert()].

    如果您只需要 反序列化 Guid 的 null 值而不是重新序列化它,则可以应用 [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] 到 Guid 属性, 和 null 值将被忽略,尽管 Guid 值无效:

    If you only need to deserialize a null value for a Guid and not re-serialize it as such, you can apply [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] to the Guid property, and null values will ignored despite being invalid Guid values:

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

    当然,如果您这样做,您的 Guid 将被重新序列化为 00000000-0000-0000-0000-000000000000".为了改善这种情况,您可以应用 DefaultValueHandling = DefaultValueHandling.Ignore 这将导致在序列化期间省略空的 Guid 值:

    Of course if you do this your Guid will be re-serialized as "00000000-0000-0000-0000-000000000000". To ameliorate that you could apply DefaultValueHandling = DefaultValueHandling.Ignore which will cause empty Guid values to be omitted during serialization:

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

    请注意,如果在反序列化期间调用的 参数化构造函数具有非-nullable Guid 参数具有相同的名称,可能需要不同的方法.

    Note that if a parameterized constructor called during deserialization has a non-nullable Guid argument with the same name, a different approach may be required.

    这篇关于Json.net 反序列化 null guid 案例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

  • 上一篇:Json.NET 序列化私有成员而不是只读属性 下一篇:从结构化数据构建 JSON 层次结构

    相关文章