If i have the following c# record:
public record MyRecord(string EndPoint, string Id);
and i have some json that i attempt to deserialize to my type:
var myType= JsonSerializer.Deserialize<MyRecord>(
jsonStr,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
}
);
if(myType is null)
{
...
}
where jsonStr
is not of type MyRecord
but some other type, the resulting myType
rather then being null, is simply an instance of MyRecord but with empty properties. How can i check that the returned type is invalid if its not null ?
CodePudding user response:
JsonSerializer
does not make assumptions about the lack of contents of a json string, provided that it is at least in the same format as the target structure (e.g. "{ }"
).
As a result, you need to check one of your properties for validity as well as the object itself:
var jsonStr = "{}";
var myType = JsonSerializer.Deserialize<MyRecord>(
jsonStr,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
}
);
if (!string.IsNullOrEmpty(myType?.Id))
{
var x = myType;
}
Note that the behavior is identical for classes as well:
public class MyClass
{
public string EndPoint { get; set; }
public string Id { get; set; }
}
var myType2 = JsonSerializer.Deserialize<MyClass>(
jsonStr,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
}
);
if (!string.IsNullOrEmpty(myType2?.Id))
{
var x = myType;
}
As mentioned in the comments, you can choose to create a custom converter that overrides the serialization behavior.
public class MyRecordConverter : JsonConverter<MyRecord>
{
public override MyRecord Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
return null;
}
var endpoint = string.Empty;
var id = string.Empty;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
var propertyName = reader.GetString();
reader.Read();
if (propertyName.Equals(nameof(MyRecord.EndPoint),
StringComparison.OrdinalIgnoreCase))
{
endpoint = reader.GetString();
}
else if (propertyName.Equals(nameof(MyRecord.Id),
StringComparison.OrdinalIgnoreCase))
{
id = reader.GetString();
}
}
if (string.IsNullOrEmpty(endpoint) && string.IsNullOrEmpty(id))
{
return null;
}
return new MyRecord(endpoint, id);
}
public override void Write(Utf8JsonWriter writer, MyRecord value,
JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
When passed to your Deserialize call:
var myType3 = JsonSerializer.Deserialize<MyRecord>(
jsonStr,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
Converters =
{
new MyRecordConverter()
}
}
);
the above empty json object will return null instead of an initialized record.