I'm using System.Text.Json
to deserialize some json. (More specifically, this call from the Last.fm API in json format)
The json that I'm trying to deserialize has a quite unconventional way of handling null values for some objects, for example when its null I get this:
"tags": "",
And like this when it has values:
"tags": {
"tag": [
{
"name": "classic rock",
"url": "https://www.last.fm/tag/classic+rock"
},
{
"name": "rock",
"url": "https://www.last.fm/tag/rock"
}
]
}
My C# class looks like this:
public class Artist
{
public Tags Tags { get; set; }
}
public class Tags
{
public Tag[] Tag { get; set; }
}
public class Tag
{
public string Name { get; set; }
public string Url { get; set; }
}
How would I check if an object is an empty string before actually trying to deserialize it?
When I try to deserialize it:
var deserializedObject = JsonSerializer.Deserialize<T>(requestBody);
It throws a System.Text.Json.JsonException: The JSON value could not be converted to FMBot.LastFM.Domain.Models.Tags. Path: $.artist.tags
error.
This call used to work when the value was actually null
, but now that it's an empty string it is broken and I can't figure out a solution.
I would use a custom converter for this task. For example:
public class TagsConverter : JsonConverter<Tags>
{
public override Tags Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
// If the token is a string, return null
if(reader.TokenType == JsonTokenType.String)
{
return null;
}
// Skip over the object and property name
reader.Read(); // Object
reader.Read(); // Property name
// Read the tags array
var tags = JsonSerializer.Deserialize<Tag[]>(ref reader, options);
reader.Read(); // Object
return new Tags { Tag = tags};
}
public override void Write(Utf8JsonWriter writer, Tags value,
JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
And use it like this:
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
Converters = { new TagsConverter() }
};
var deserializedObject = JsonSerializer.Deserialize<Artist>(requestBody, options );