问题描述
我正在使用 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)null
a> 并且您将看到一条错误消息,指示无法在 .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:
创建一个
Guid?
可为空的代理属性.如果您愿意,它可以是私有的,只要它具有[JsonProperty]
属性:
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); } }
}
创建一个 JsonConverter
将 null
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 案例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!