System.Text.Json JsonConverter 字符串数组到单个字符串

System.Text.Json JsonConverter String array to single string

我想转换以下JSON。如您所见,数组只有一个条目。我想把它转换成一个简单的字符串。

{
    "@timestamp": [
        "2022-05-24T01:53:32.600Z"
    ],
    "site.siteCode": [
        "ZAR"
    ],
    "username": [
        "QR02159T1"
    ]
}

我试图用 System.Text.Json 创建一个 JsonConverter,但尽管添加了转换器,但它从未调用过。

我的转换器

public class ArrayToSingleConverter : JsonConverter<string>
    {
        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.StartArray)
            {
                // Proper array, we can deserialize from this token onwards.
                // return JsonSerializer.Deserialize<List<string>>(ref reader, options);
            }

            throw new NotImplementedException();
        }

        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }
    }

模特

public class Ad4p 
    {
        [JsonPropertyName("site.siteCode")]
        [JsonConverter(typeof(ArrayToSingleConverter))]
        public string Sitecode { get; set; }

        [JsonPropertyName("username")]
        [JsonConverter(typeof(ArrayToSingleConverter))]
        public string Username { get; set; }

        [JsonPropertyName("@timestamp")]
        [JsonConverter(typeof(ArrayToSingleConverter))]
        public string Timestamp { get; set; }
    }

实施

_jsonOptions.Converters.Add(new ArrayOrObjectJsonConverter<string>());
var ad4pList = JsonSerializer.Deserialize<Ad4p>(json, _jsonOptions);

但是我有以下错误 抛出异常:System.Text.Json.dll 中的 'System.InvalidOperationException':''CrawlerPowerBi.Models.Ad4p.Sitecode' 上指定的转换器与类型 'System.String' 不兼容。'

如何将字符串或对象数组转换为单个字符串或对象? 谢谢

经过一些尝试并参考了类似的例子Support round trip for Stack,

JsonSerializerOptions _jsonOptions = new JsonSerializerOptions();
var ad4pList = JsonSerializer.Deserialize<Ad4p>(json, _jsonOptions);
public class ArrayToSingleConverter : JsonConverter<string>
{

    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartArray)
        {
            throw new JsonException();
        }

        List<string> list = new List<string>();
        
        reader.Read();
        
        while (reader.TokenType != JsonTokenType.EndArray)
        {
            list.Add(JsonSerializer.Deserialize<string>(ref reader, options));

            reader.Read();
        }
        
        return list.FirstOrDefault();
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

支持通用

public class ArrayToSingleConverter<T> : JsonConverter<T>
{

    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartArray)
        {
            throw new JsonException();
        }

        List<T> list = new List<T>();
        
        reader.Read();
        
        while (reader.TokenType != JsonTokenType.EndArray)
        {
            list.Add(JsonSerializer.Deserialize<T>(ref reader, options));

            reader.Read();
        }
        
        return list.FirstOrDefault();
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}
public class Ad4p
{
    [JsonPropertyName("site.siteCode")]
    [JsonConverter(typeof(ArrayToSingleConverter<string>))]
    public string Sitecode { get; set; }

    [JsonPropertyName("username")]
    [JsonConverter(typeof(ArrayToSingleConverter<string>))]
    public string Username { get; set; }

    [JsonPropertyName("@timestamp")]
    [JsonConverter(typeof(ArrayToSingleConverter<string>))]
    public string Timestamp { get; set; }
}

Demo on .NET Fiddle


选择:

reader.Read();
        
while (reader.TokenType != JsonTokenType.EndArray)
{
    list.Add(JsonSerializer.Deserialize<T>(ref reader, options));

    reader.Read();
}

可以替换为:

while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
{
    list.Add(JsonSerializer.Deserialize<T>(ref reader, options));
}

因为两者都旨在读取 JSON 值,直到找到 EndArray

Demo on .NET Fiddle (Alternative)