Having a <nullable>enabled</nullable>
in project settings, having the following class
public class Car
{
public required string Name { get; init; }
}
and deserializing it from string:
System.Text.Json.JsonSerializer.Deserialize<Car>("""{"Name": null}""");
Does not throw an exception
Because property is marked as not nullable, is it possible to configure STJ to throw in case of null
value?
CodePudding user response:
Since you are using .NET 7 and C# 11 by the looks from required modifier, you could try using JsonRequiredAttribute from System.Text.Json package.
Alternatively there is a similar option in Newtonsoft.Json package.
public class Car
{
[JsonProperty(Required = Required.Always)]
public string Name { get; init; }
}
CodePudding user response:
required
as JsonRequiredAttribute
results in JsonTypeInfo.IsRequired
set to true and have same behaviour - throws only if the corresponding property is not present in the json (docs):
Starting in .NET 7, you can mark certain properties to signify that they must be present in the JSON payload for deserialization to succeed.
If you want to catch the properties being set to null you can leverage the ability to customize the serialization contract. You can start from the following:
private static void ThrowNullableRequired(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Kind != JsonTypeInfoKind.Object)
{
return;
}
foreach (var property in jsonTypeInfo.Properties)
{
if (property.IsRequired && !property.PropertyType.IsValueType && property.Set is { } setter)
{
// not sure maybe should cache nullability checks
NullabilityInfoContext context = new();
var nullabilityInfo = context.Create(jsonTypeInfo.Type.GetProperty(property.Name));
if (nullabilityInfo.WriteState is not NullabilityState.NotNull)
{
continue;
}
property.Set = (obj, val) =>
{
if (val is null)
{
throw new JsonException($"null for required prop: {property.Name}");
}
setter(obj, val);
};
}
}
}
And usage:
var settings = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { ThrowNullableRequired }
}
};
try
{
var myClass1 = JsonSerializer.Deserialize<Car>(
"""
{
"Name":null,
"Prefix":null
}
""", settings);
}
catch (Exception e)
{
}
var car = JsonSerializer.Deserialize<Car>(
"""
{
"Name":"a",
"Prefix":null
}
""", settings);