You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理NUnit测试报告中同一Key对应不同类型的JSON反序列化问题?

处理NUnit测试报告中test-suite的单对象/数组兼容反序列化

针对NUnit测试报告里test-suite字段时而为单个对象、时而为数组的情况,你可以通过自定义JSON转换器的方式,让反序列化逻辑自动兼容两种格式。下面针对.NET生态里最常用的两个JSON库分别给出实现方案:

一、使用Newtonsoft.Json(Json.NET)

1. 定义基础实体类

先写出TestSuite的基础结构(根据实际报告字段调整):

public class TestSuite
{
    public string Name { get; set; }
    public string Type { get; set; }
    // 其他需要的字段...
}

public class NUnitReport
{
    // 用List<TestSuite>统一接收,配合自定义转换器
    [JsonConverter(typeof(SingleOrArrayConverter<TestSuite>))]
    public List<TestSuite> TestSuites { get; set; }
    // 报告里的其他字段...
}

2. 自定义转换器

创建通用的单对象/数组兼容转换器,复用性更强:

public class SingleOrArrayConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        return token.Type switch
        {
            JTokenType.Array => token.ToObject<List<T>>(),
            JTokenType.Object => new List<T> { token.ToObject<T>() },
            _ => throw new JsonSerializationException($"Unexpected token type: {token.Type}")
        };
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        if (value.Count == 1)
        {
            serializer.Serialize(writer, value[0]);
        }
        else
        {
            serializer.Serialize(writer, value);
        }
    }
}

3. 反序列化使用

直接正常调用反序列化方法即可:

var report = JsonConvert.DeserializeObject<NUnitReport>(jsonContent);

二、使用System.Text.Json(.NET Core/.NET 5+原生库)

1. 定义基础实体类

同样先定义TestSuite和报告类,注意转换器特性的区别:

public class TestSuite
{
    public string Name { get; set; }
    public string Type { get; set; }
    // 其他字段...
}

public class NUnitReport
{
    [JsonConverter(typeof(SingleOrArrayConverter<TestSuite>))]
    public List<TestSuite> TestSuites { get; set; }
    // 其他报告字段...
}

2. 自定义转换器

实现System.Text.Json的转换器接口:

public class SingleOrArrayConverter<T> : JsonConverter<List<T>>
{
    public override List<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var list = new List<T>();
        if (reader.TokenType == JsonTokenType.StartArray)
        {
            while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
            {
                var item = JsonSerializer.Deserialize<T>(ref reader, options);
                if (item != null)
                {
                    list.Add(item);
                }
            }
        }
        else if (reader.TokenType == JsonTokenType.StartObject)
        {
            var item = JsonSerializer.Deserialize<T>(ref reader, options);
            if (item != null)
            {
                list.Add(item);
            }
        }
        else
        {
            throw new JsonException($"Unexpected token type: {reader.TokenType}");
        }
        return list;
    }

    public override void Write(Utf8JsonWriter writer, List<T> value, JsonSerializerOptions options)
    {
        if (value.Count == 1)
        {
            JsonSerializer.Serialize(writer, value[0], options);
        }
        else
        {
            JsonSerializer.Serialize(writer, value, options);
        }
    }
}

3. 反序列化使用

调用原生的反序列化方法:

var report = JsonSerializer.Deserialize<NUnitReport>(jsonContent);

三、简易替代方案(无需自定义转换器)

如果不想写转换器,也可以在报告类里用私有字段配合公共属性做转换:

public class NUnitReport
{
    // 先接收原始的单对象或数组
    private object _testSuite;

    // 对外暴露统一的List<TestSuite>
    [JsonIgnore]
    public List<TestSuite> TestSuites
    {
        get
        {
            return _testSuite switch
            {
                TestSuite suite => new List<TestSuite> { suite },
                IEnumerable<TestSuite> suiteArray => suiteArray.ToList(),
                _ => new List<TestSuite>()
            };
        }
    }

    // 让JSON序列化器映射到私有字段
    [JsonPropertyName("test-suite")]
    public object TestSuiteRaw
    {
        get => _testSuite;
        set => _testSuite = value;
    }

    // 其他报告字段...
}

这种方式适合快速临时处理,但复用性不如自定义转换器。

内容的提问来源于stack exchange,提问作者Milan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:44:59