C# 如何使用JSON.NET处理有时是对象,有时是对象数组的值?

C# 如何使用JSON.NET处理有时是对象,有时是对象数组的值?,c#,json.net,json-deserialization,C#,Json.net,Json Deserialization,我注意到关于这个问题的stackoverflow还有一些其他的结果,但它们似乎不起作用或者是模糊的。使用最流行的结果,我总结了以下内容: 问题是,当JSON返回并被序列化为我的一种自定义类型时,JSON的一个位有时是一个数组,有时只是一个字符串。如果我的自定义类型有一个字符串,而JSON是一个数组,我会得到一个错误。如果JSON是一个对象,而我的自定义类型是一个数组,则情况也是如此。它只是无法将其映射到属性 我决定解决这个问题,我想覆盖这个特殊属性的反序列化,如果它是一个对象,我想把它转换成一个

我注意到关于这个问题的stackoverflow还有一些其他的结果,但它们似乎不起作用或者是模糊的。使用最流行的结果,我总结了以下内容:

问题是,当JSON返回并被序列化为我的一种自定义类型时,JSON的一个位有时是一个数组,有时只是一个字符串。如果我的自定义类型有一个字符串,而JSON是一个数组,我会得到一个错误。如果JSON是一个对象,而我的自定义类型是一个数组,则情况也是如此。它只是无法将其映射到属性

我决定解决这个问题,我想覆盖这个特殊属性的反序列化,如果它是一个对象,我想把它转换成一个由1个对象组成的数组

在序列化到的对象中,我添加了一个JsonConverter,我认为它将覆盖反序列化的方式

[JsonConverter(typeof(ArrayOrSingleObjectConverter<string>))]
public List<string> person { get; set; }
[JsonConverter(typeof(ArrayOrSingleObjectConverter))]
公共列表人员{get;set;}
其思想是自定义转换器将单个对象转换为数组。因此,如果JSON是“Hello”,它会将person设置为包含“Hello”的列表,而不是抛出一个异常,表示无法将字符串转换为列表

如果它已经是一个数组,就应该不使用它

转换器如下所示:

public class ArrayOrSingleObjectConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true; // Not sure about this but technically it can accept an array or an object, so everything is game.
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (objectType == typeof(List<T>))
        {
            return serializer.Deserialize<List<T>>(reader);
        }
        else
        {
            var singleObject = serializer.Deserialize<T>(reader);
            var objectAsList = new List<T>();
            objectAsList.Add(singleObject);
            return objectAsList;
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
公共类ArrayOrSingleObjectConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
return true;//对此不确定,但技术上它可以接受数组或对象,所以一切都是游戏。
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(objectType==typeof(List))
{
返回序列化程序。反序列化(读取器);
}
其他的
{
var singleObject=序列化程序。反序列化(读取器);
var objectAsList=新列表();
objectAsList.Add(singleObject);
返回objectAsList;
}
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
}
它不起作用。上面的代码抛出一个异常,试图反序列化单个字符串,表示它无法将其强制转换到if语句中的列表中(“objectype”不过是一个列表)

我正在努力理解读写方法到底在做什么。在stackoverflow的另一个答案中,它建议在read方法中抛出一个
NotImplementedException
。但是如果我这样做,就会调用read方法,并抛出异常

我想我走的是对的,但我需要一个正确的方向。我想我对ReadJSon方法正在做什么以及它的参数意味着什么有些困惑

我真的不明白这个值是从哪里来的,因为我没有在反序列化方法调用中指定它


在这一点上,我有点不知所措。

上周我不得不做一些类似的事情,我提出了以下建议,它适用于列表而不是数组

 internal class GenericListCreationJsonConverter<T> : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize<List<T>>(reader);
        }
        else
        {
            T t = serializer.Deserialize<T>(reader);
            return new List<T>(new[] { t });
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
内部类GenericListCreationJsonConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回true;
}
公共覆盖布尔可读取
{
获取{return true;}
}
公共覆盖布尔可写
{
获取{return false;}
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.StartArray)
{
返回序列化程序。反序列化(读取器);
}
其他的
{
T=序列化程序。反序列化(读取器);
返回新列表(new[]{t});
}
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}

我喜欢这种让Json.NET承担所有繁重工作的方法。因此,它支持Json.NET支持的任何东西(列表、ArrayList、强类型数组等)


你不能将“variable”对象反序列化为
系统。对象
?然后你可以检查运行时类型并执行你的操作。非常感谢,我最终找到了类似的方法,但我喜欢你的方法,因为我在与泛型作斗争:)
public class FlexibleCollectionConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize(reader, objectType);
        }

        var array = new JArray(JToken.ReadFrom(reader));
        return array.ToObject(objectType);
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof (IEnumerable).IsAssignableFrom(objectType);
    }
}