System.Text.Json - 反序列化既可以是空字符串又可以是类的对象

4

我正在使用System.Text.Json来反序列化一些json数据。(更具体地说,是来自Last.fm API的此调用以json格式返回)

我试图反序列化的json处理某些对象的null值的方式相当不寻常,例如当其为null时,我会得到以下结果:

    "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时可以正常工作,但是现在值变成了空字符串,导致它无法正常运行,我无法找到解决方案。


1
公共API基本上像那样进行根本性的更改是相当糟糕的做法 - 上一次.fm真是太丢人了。话虽如此,您需要编写一个JsonConverter来明确处理此情况。请参见:https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to - Chris Pickford
2个回答

4
我会使用自定义转换器来完成这项任务。例如:
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 );

0

解决这个问题的一种简单方法是将Tags属性的类型更改为dynamic

public class Artist
{
    public dynamic Tags { get; set; }
}

您可以检查Tags is Tag[]Tags is string,并采取相应的措施。不要忘记还要检查它既不是上述两种情况中的任何一种(可能会抛出异常)。

1
请不要使用 dynamic,每次使用都会有一只小猫死去。 - DavidG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接