问题描述
我正在使用 System.Text.Json
反序列化一些 json。 (更具体地说,this call 来自 json 格式的 Last.fm API)
我试图反序列化的 json 有一种非常规的方式来处理某些对象的空值,例如,当它为空时,我得到了这个:
"tags": "",
当它有值时就像这样:
"tags": {
"tag": [
{
"name": "classic rock","url": "https://www.last.fm/tag/classic+rock"
},{
"name": "rock","url": "https://www.last.fm/tag/rock"
}
]
}
我的 C# 类如下所示:
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; }
}
在实际尝试反序列化对象之前,如何检查对象是否为空字符串?
当我尝试反序列化时:
var deserializedobject = JsonSerializer.Deserialize<T>(requestBody);
它抛出一个 System.Text.Json.JsonException: The JSON value Could not be converted to FMBot.LastFM.Domain.Models.Tags. Path: $.artist.tags
错误。
当值实际上是 null
时,这个调用曾经可以工作,但现在它是一个空字符串,它被破坏了,我想不出解决办法。
解决方法
我会为此任务使用自定义转换器。例如:
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();
}
}
像这样使用它:
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,Converters = { new TagsConverter() }
};
var deserializedObject = JsonSerializer.Deserialize<Artist>(requestBody,options );
,
解决此问题的一种简单方法是将 Tags
属性的类型更改为 dynamic
。
public class Artist
{
public dynamic Tags { get; set; }
}
然后您可以检查是 Tags is Tag[]
还是 Tags is string
并采取相应的行动。不要忘记检查它是否不是上述任何一个(并且可能抛出)。