Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何告诉JSON.NET将JArray反序列化到列表<;对象>;何时提供对象类型?_C#_.net_Json_Json.net - Fatal编程技术网

C# 如何告诉JSON.NET将JArray反序列化到列表<;对象>;何时提供对象类型?

C# 如何告诉JSON.NET将JArray反序列化到列表<;对象>;何时提供对象类型?,c#,.net,json,json.net,C#,.net,Json,Json.net,让我们来上下面的课: class Foo { public object Any; } 此类接受字段Any中的任何内容 当我打电话时: JsonConvert.DeserializeObject<Foo>("{any: 5}") JsonConvert.DeserializeObject<Foo>("{any: [5]}") Any包含Newtonsoft.Json.Linq.JArray 如何配置JSON.NET,以便在本例中,任何都包含列表 澄清: 可能

让我们来上下面的课:

class Foo
{
    public object Any;
}
此类接受字段
Any
中的任何内容

当我打电话时:

JsonConvert.DeserializeObject<Foo>("{any: 5}")
JsonConvert.DeserializeObject<Foo>("{any: [5]}")
Any
包含
Newtonsoft.Json.Linq.JArray

如何配置JSON.NET,以便在本例中,
任何
都包含
列表

澄清:

可能有什么,我可以打电话:

JsonConvert.DeserializeObject<Foo>("{any: 'c'}")
JsonConvert.DeserializeObject(“{any:'c'}”)

JsonConvert.DeserializeObject(“{any:['c',5]}”)
更多澄清:

我想告诉JSON.NET(可能使用JsonSerializerSettings):

当遇到
对象
且JSON包含数组时,反序列化该数组 到(例如)
列表

你的答案可能是

您的
[5]
是一个数组。你所要做的就是把它放到一个列表中



您还可以创建自己的转换器,如

我认为您可以使用JsonConverter来实现这一点。当any字段是JArray时,下面的转换器将JArray转换为对象列表,并在所有其他情况下返回到any的默认行为。根据你的描述,这正是你想要的。我怀疑代码可以改进,但这应该为您提供解决方案:

public class ListJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        var theFoo = new Foo();

        dynamic dynamicObject = serializer.Deserialize(reader);

        if (dynamicObject.any.GetType() == typeof (JArray))
        {
            var items = new List<object>();

            foreach (var item in dynamicObject.any)
            {
                items.Add(item);
            }

            theFoo.Any = items;
        }
        else
        {
            theFoo.Any = dynamicObject.any.Value;
        }

        return theFoo;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (Foo);
    }

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

    public override bool CanWrite
    {
        get { return false; }
    }
}
public class MyObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object);
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case Newtonsoft.Json.JsonToken.StartArray:
                return JToken.Load(reader).ToObject<List<object>>(); 
            case Newtonsoft.Json.JsonToken.StartObject:
                return JToken.Load(reader).ToObject<Dictionary<string, object>>(); 
            default:
                if (reader.ValueType == null && reader.TokenType != Newtonsoft.Json.JsonToken.Null)
                    throw new NotImplementedException("MyObjectConverter");
                return reader.Value;
        }
    }

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

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException("MyObjectConverter");
    }
}
公共类列表JsonConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
public override object ReadJson(JsonReader reader,Type objectType,object existingValue,
JsonSerializer(序列化程序)
{
var theFoo=newfoo();
DynamicDynamicObject=serializer.Deserialize(读取器);
if(dynamicObject.any.GetType()==typeof(JArray))
{
var items=新列表();
foreach(dynamicObject.any中的变量项)
{
项目。添加(项目);
}
theFoo.Any=项目;
}
其他的
{
theFoo.Any=dynamicObject.Any.Value;
}
返回theFoo;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(Foo);
}
公共覆盖布尔可读取
{
获取{return true;}
}
公共覆盖布尔可写
{
获取{return false;}
}
}
用法:

var bar = JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}", new ListJsonConverter());
var bar=JsonConvert.DeserializeObject(“{any:['c',5]}”,new ListJsonConverter());

目前,我模拟了以下解决方案:

public class ListJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        var theFoo = new Foo();

        dynamic dynamicObject = serializer.Deserialize(reader);

        if (dynamicObject.any.GetType() == typeof (JArray))
        {
            var items = new List<object>();

            foreach (var item in dynamicObject.any)
            {
                items.Add(item);
            }

            theFoo.Any = items;
        }
        else
        {
            theFoo.Any = dynamicObject.any.Value;
        }

        return theFoo;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (Foo);
    }

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

    public override bool CanWrite
    {
        get { return false; }
    }
}
public class MyObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object);
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case Newtonsoft.Json.JsonToken.StartArray:
                return JToken.Load(reader).ToObject<List<object>>(); 
            case Newtonsoft.Json.JsonToken.StartObject:
                return JToken.Load(reader).ToObject<Dictionary<string, object>>(); 
            default:
                if (reader.ValueType == null && reader.TokenType != Newtonsoft.Json.JsonToken.Null)
                    throw new NotImplementedException("MyObjectConverter");
                return reader.Value;
        }
    }

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

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException("MyObjectConverter");
    }
}
公共类MyObjectConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(对象);
}
public override object ReadJson(Newtonsoft.Json.JsonReader reader,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
开关(reader.TokenType)
{
案例Newtonsoft.Json.JsonToken.StartArray:
返回JToken.Load(reader.ToObject();
案例Newtonsoft.Json.JsonToken.StartObject:
返回JToken.Load(reader.ToObject();
违约:
if(reader.ValueType==null&&reader.TokenType!=Newtonsoft.Json.JsonToken.null)
抛出新的NotImplementedException(“MyObjectConverter”);
返回reader.Value;
}
}
公共覆盖布尔可写
{
获取{return false;}
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer,对象值,JsonSerializer序列化程序)
{
抛出新的NotSupportedException(“MyObjectConverter”);
}
}

这个解决方案的问题是它还必须处理其他类型。当reader.TokenType既不是
StartArray
也不是
StartObject
且reader.ValueType为空时,它可能会失败。希望有人能提供一个更好的解决方案。

可能重复的@AndrewHitaker请参见更新。如果
任何
只是
5
,而不是
[5]
,您希望它也成为
列表吗?@Daniel不,因为可能有[5,'x']。(因此,我将
object
放在那里。)您可以使用jsonstructuratribute()标记构造函数,这将告诉它在反序列化对象时使用该构造函数。然后你可以在里面放任何你想要的逻辑。这对您有用吗?我不想重新转换结构,检查并强制转换所有对象类型的字段。如何指定仅当JSON包含数组(且成员类型为object)时才调用转换?或者,当JSON包含(例如)字符串时,如何回退到默认行为?感谢您的代码,但是
Foo
只是一个示例。我无法为特定的类(
Foo
)和属性(
Any
)硬连线转换器。你的意思是,你想让它用于任何类型的对象吗?像Foo1、Foo2、Foo3和其他任何类型?@Daniel是的,我尝试在这里模拟解决方案:。您不需要转换所有类型。你只需要转换你想要的类型。如果我理解得很好,您只需要实现
数组
的情况,任何其他情况下,您只需返回原样的对象,JSON将完成其余的工作。(它能够在没有转换器的情况下管理这些类型,对吗?)但是,我在其他情况下从何处获得“对象”?ToObject没有正确地反序列化嵌套数组(例如
[1,5,3]
[1,{bar:[4]}]
)。同样的问题目前也有上述解决方案。如果只删除
if
,是否会出现异常?可能不会,但想知道读取器在
值中是否包含
null
,因为它应该在那里。但你可以忽略这一点,如果。问题是
JToken.Load(reader).ToObject()
不处理嵌套数组,也可能不处理其他JSONConvertor