Does the new `System.Text.Json` have a required property attribute?
Not as of .NET Core 3.0. The only ones supported are:
JsonConverterAttribute
JsonExtensionDataAttribute
JsonIgnoreAttribute
JsonPropertyNameAttribute
Update: In .NET 5.0 the set is
JsonConstructorAttribute
JsonConverterAttribute
JsonExtensionDataAttribute
JsonIgnoreAttribute
JsonIncludeAttribute
JsonNumberHandlingAttribute
JsonPropertyNameAttribute
Unfortunately even a custom converter with HandleNull => true
shown in How to write custom converters for JSON serialization (marshalling) in .NET won't work because if the property in not present Read and Write methods are not called (tested in 5.0, and a modified version in 3.0)
public class Radiokiller
{
[JsonConverter(typeof(MyCustomNotNullConverter))]
public string Name { get; set; }
}
public class MyCustomNotNullConverter : JsonConverter<string>
{
public override bool HandleNull => true;
public override string Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.GetString() ?? throw new Exception("Value required.");
public override void Write(
Utf8JsonWriter writer,
string value,
JsonSerializerOptions options) =>
writer.WriteStringValue(value);
}
var json = "{}";
var o = JsonSerializer.Deserialize<Radiokiller>(json); // no exception :(
json = "{ \"Name\" : null}";
o = JsonSerializer.Deserialize<Radiokiller>(json); // throws
As of 5.0, you can achieve this using constructors. Any exceptions will bubble up during deserialization.
public class Videogame
{
public Videogame(string name, int? year)
{
this.Name = name ?? throw new ArgumentNullException(nameof(name));
this.Year = year ?? throw new ArgumentNullException(nameof(year));
}
public string Name { get; }
[NotNull]
public int? Year { get; }
}
N.B. The library won't throw an error if a constructor argument is missing from the JSON. It just uses the default value for the type (so 0
for int
). It's a good idea to use nullable value types if you want to handle that scenario.
Also, the types of constructor parameters must match your fields/properties exactly, so no going from int?
to int
, unfortunately. I've found the analysis attributes [NotNull]
and/or [DisallowNull]
, in the System.Diagnostics.CodeAnalysis namespace, make this less inconvenient.
Please try this library I wrote as an extension to System.Text.Json to offer missing features: https://github.com/dahomey-technologies/Dahomey.Json.
You will find support for JsonRequiredAttribute.
public class Videogame
{
[JsonRequired(RequirementPolicy.Always)]
public string Name { get; set; }
}
Setup json extensions by calling on JsonSerializerOptions the extension method SetupExtensions defined in the namespace Dahomey.Json. Then deserialize your class with the regular Sytem.Text.Json API.
JsonSerializerOptions options = new JsonSerializerOptions();
options.SetupExtensions();
const string json = @"{""Name"":""BGE2""}";
Videogame obj = JsonSerializer.Deserialize<Videogame>(json, options);