C# NewtonSoft 单一对象或数组 JsonConverter 不工作,没有错误

C# NewtonSoft Single Object or Array JsonConverter not working, no errors

我正在尝试反序列化一些 JSON,它有时是一个数组,有时是一个对象。由于项目限制,它必须被推广。我查看了这个 Stack Overflow 问题 (Deserializing JSON when sometimes array and sometimes object),但该代码不适用于我的单元测试。它也没有错误,并且调试器显示在转换器内部它正在 returning 对象,就像它应该的那样。

当我说它不起作用时,它反序列化所有内容,直到它到达有问题的 JSON 元素,然后它只是序列化为一个空数组,如下所示:

"a": []

这是我的测试JSON:

{
    "somefile": [
        {
            "name": "Bob",
            "a": {
                "asub": "Bob",
                "atracking": "Bob",
                "adate": " Bob"
            }
        },
        {
            "name": "Bob",
            "a": [
                {
                    "asub": "Bob",
                    "atracking": "Bob",
                    "adate": "Bob"
                },
                {
                    "asub": "Bob",
                    "atracking": "Bob",
                    "adate": "Bob"
                }
            ]
        }
    ]
}

这是我的 C# 数据模型,底部有转换器:

public class DummyDataModel
{
    public List<SomeFile> someFile { get; } = new List<SomeFile>();
    public partial class SomeFile
    {
        public string name { get; set; } = "";

        [JsonConverter(typeof(SingleObjectOrArrayJsonConverter<SomeA>))]
        public List<SomeA> a { get; } = new List<SomeA>();
        //public SomeA a { get; set; } = new SomeA();
    }
    public partial class SomeA
    {
        public string asub { get; set; } = "";
        public string atracking { get; set; } = "";
        public string adate { get; set; } = "";
    }


    internal class SingleObjectOrArrayJsonConverter<T> : JsonConverter<List<T>> where T : class, new()
    {
        public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, value.Count == 1 ? (object)value.Single() : value);
        }

        public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            return reader.TokenType switch
            {
                JsonToken.StartObject => new List<T> { serializer.Deserialize<T>(reader) },
                JsonToken.StartArray => serializer.Deserialize<List<T>>(reader),
                _ => throw new ArgumentOutOfRangeException($"Converter does not support JSON token type {reader.TokenType}.")
            };
        }
    }
}

关于为什么它可以毫无错误地完成每个步骤但仍然 return 没有任何提示的任何提示?

这是 运行 此测试的行(我使用的是 WPF 和 C# 8.0)

DummyDataModel uTest = JsonConvert.DeserializeObject<DummyDataModel>(unitJSON);

txtResult.Text = $"Did Test:\n{JsonConvert.SerializeObject(uTest, Formatting.Indented)}";

您的 a 属性 是 get-only,因此在您的 ReadJson() 方法中您需要填充传入的 List<T> existingValue 列表(这将是当前的 属性 值)而不是创建一个新列表:

internal class SingleObjectOrArrayJsonConverter<T> : JsonConverter<List<T>> where T : class, new()
{
    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) =>
        // avoid possibility of infinite recursion by wrapping the List<T> with AsReadOnly()
        serializer.Serialize(writer, value.Count == 1 ? (object)value.Single() : value.AsReadOnly());

    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        existingValue ??= new ();
        switch (reader.TokenType)
        {
            case JsonToken.StartObject: existingValue.Add(serializer.Deserialize<T>(reader)); break;
            case JsonToken.StartArray: serializer.Populate(reader, existingValue); break;
            default: throw new ArgumentOutOfRangeException($"Converter does not support JSON token type {reader.TokenType}.");
        };
        return existingValue;
    }
}

另请参阅 this answer to How to handle both a single item and an array for the same property using JSON.net,它显示了一个类似但更通用的转换器。

演示 fiddle here.