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

ara*_*iel 2 c# json converters jsonconverter system.text.json

我想转换以下 JSON。如您所见,该数组只有一个条目。我想将其转换为一个简单的字符串。

{
    "@timestamp": [
        "2022-05-24T01:53:32.600Z"
    ],
    "site.siteCode": [
        "ZAR"
    ],
    "username": [
        "QR02159T1"
    ]
}
Run Code Online (Sandbox Code Playgroud)

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

我的转换器:

{
    "@timestamp": [
        "2022-05-24T01:53:32.600Z"
    ],
    "site.siteCode": [
        "ZAR"
    ],
    "username": [
        "QR02159T1"
    ]
}
Run Code Online (Sandbox Code Playgroud)

该模型:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

实施:

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; }
}
Run Code Online (Sandbox Code Playgroud)

但我有以下错误:

抛出异常:System.Text.Json.dll 中的“System.InvalidOperationException”:“在“CrawlerPowerBi.Models.Ad4p.Sitecode”上指定的转换器与类型“System.String”不兼容。”

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

Yon*_*hun 6

经过一番尝试并参考类似的示例Support round trip for Stack

JsonSerializerOptions _jsonOptions = new JsonSerializerOptions();
var ad4pList = JsonSerializer.Deserialize<Ad4p>(json, _jsonOptions);
Run Code Online (Sandbox Code Playgroud)
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();
    }
}
Run Code Online (Sandbox Code Playgroud)

支持通用

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();
    }
}
Run Code Online (Sandbox Code Playgroud)
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();
    }
}
Run Code Online (Sandbox Code Playgroud)

.NET Fiddle 上的演示


选择:

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; }
}
Run Code Online (Sandbox Code Playgroud)

可以替换为:

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

    reader.Read();
}
Run Code Online (Sandbox Code Playgroud)

因为两者的目的都是读取 JSON 值,直到EndArray找到为止。

.NET Fiddle 演示(替代)