Reputation: 392
With an attribute [JsonProperty(Required = Required.Always)]
annotating my model I am able to check, that the property value is not null.
For strings I would like to check for empty values as well. Is there a way to check if string property value is empty while using attributes in Json.NET? Or is there any other way?
This JSON should cause a problem
{
"Property1": "",
...
}
Upvotes: 1
Views: 3308
Reputation: 1196
By using a JSON schema you can define minimum lengths for specific properties, among other things. This is reasonably simple using the additional Json.NET Schema package, after slight modifications to the deserialization code to specify the schema to be used for validation. However, the Json.NET Schema library is not MIT licensed and uses restrictive/commercial licensing unlike Json.NET itself. There may be other implementations, though.
In a similar case I ended up (ab)using a JsonConverter
to do validation instead. This is somewhat hacky as it's not really a converter, but the convenient thing is that it works purely by applying a Json.NET attribute to the model without any other code changes.
public class NonEmptyStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(string);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
=> throw new NotImplementedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.String)
throw CreateException($"Expected string value, but found {reader.TokenType}.", reader);
var value = (string)reader.Value;
if (String.IsNullOrEmpty(value))
throw CreateException("Non-empty string required.", reader);
return value;
}
private static Exception CreateException(string message, JsonReader reader)
{
var info = (IJsonLineInfo)reader;
return new JsonSerializationException(
$"{message} Path '{reader.Path}', line {info.LineNumber}, position {info.LinePosition}.",
reader.Path, info.LineNumber, info.LinePosition, null);
}
}
Usage:
[JsonProperty(Required = Required.Always)]
[JsonConverter(typeof(NonEmptyStringConverter))]
public string Property1 { get; set; }
The Required.Always
should still be applied to handle cases where the property is missing completely, in which case the converter won't be called by Json.NET.
Upvotes: 5