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