Json.net deserialization null guid case
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:
-
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); } } } -
Create a
JsonConverterthat converts anullJson 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; } }Alternatively, you can apply the converter to all values of type
Tby adding the converter toJsonSerializerSettings.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.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()].
-
If you only need to deserialize a
nullvalue for a Guid and not re-serialize it as such, you can apply[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]to the Guid property, andnullvalues will ignored despite being invalid Guid values:public class MyClass { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public Guid Property { get; set; } }Of course if you do this your Guid will be re-serialized as
"00000000-0000-0000-0000-000000000000". To ameliorate that you could applyDefaultValueHandling = DefaultValueHandling.Ignorewhich will cause empty Guid values to be omitted during serialization:[JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] public Guid Property { get; set; }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.
Related videos on Youtube
Comments
-
Adrian Buzea 11 monthsI'm deserializing an object using
Json.NETthat contains a private field of type Guid and a public property for that field. When the value for myGuidis null in my json I want to assignGuid.Emptyto 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
deserializerwants 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?
-
Adrian Buzea almost 8 yearsThank you! One question about the Null to default converter. Do I have to manually add the JsonConverter attribute to each field/property in my class or can I somehow add it for all the properties in the class ? -
dbc almost 8 yearsYou can either add it to each property or register it for use globally in all classes. See Registering a custom JsonConverter in Json.Net. -
Efreeto almost 3 yearsThe 3rd option was exactly what I needed. Thank you for providing extensive answers for possible use cases.