C# 如何转换列表中的每个对象<;ExpandoObject>;变成它自己的类型?
我有一个变量C# 如何转换列表中的每个对象<;ExpandoObject>;变成它自己的类型?,c#,json,serialization,dynamic,C#,Json,Serialization,Dynamic,我有一个变量输入定义为列表 这是jsonList反序列化的结果,jsonList是由不同结构的对象组成的JSON数组: dynamic inputs = JsonConvert.DeserializeObject<List<ExpandoObject>>(jsonList, converter); 基本上,我希望在循环内部将input对象转换为input.type中指定为字符串的相应类型 感谢您的帮助 编辑 在这里面,对于每个循环,我想做如下操作: var json =
输入
定义为列表
这是jsonList反序列化的结果,jsonList是由不同结构的对象组成的JSON数组:
dynamic inputs = JsonConvert.DeserializeObject<List<ExpandoObject>>(jsonList, converter);
基本上,我希望在循环内部将input对象转换为input.type中指定为字符串的相应类型
感谢您的帮助
编辑
在这里面,对于每个循环,我想做如下操作:
var json = JsonConvert.SerializeObject(input);
Type T = Type.GetType(string.Format("WCFService.{0}", input.Type));
T obj = JsonConvert.DeserializeObject<typeof(T)>(json); // this line fails compilation
private T convertTo<T>(string json)
{
return (T)JsonConvert.DeserializeObject(json, typeof(T));
}
var json = // some serialized json ...
var o = convertTo<MyCustomType>(json);
煅烧类型1、煅烧类型2和最可能的煅烧类型3、4、5。。。该数组中此类对象的类型是否
解决方案
感谢大家的帮助,特别是建议使用JObject而不是ExpandoObject,这使解决方案变得更加简单和简单:
注意:“thing”永远不会起作用,因为在本例中T必须在编译时已知,但我需要在运行时确定类型,因此解决方案如下:
public CalcOutputTypes Calculate2(string jsonList)
{
var jobjects = JsonConvert.DeserializeObject<List<JObject>>(jsonList);
foreach (var jobject in jobjects)
{
Type runtimeType = Type.GetType(string.Format("WCFService.{0}", jobject.GetValue("TYPE")));
var input = jobject.ToObject(runtimeType); // Here we convert JObject to the defined type that just created runtime
// At this moment you have a strongly typed object "input" (CalcInputTypes1 or CalcInputTypes2 or...)
}
return new CalcOutputTypes() { STATUS = "Everything is OK !! (input was: json array of heterogeneous objects)" }; // HERE YOU RETURN CalcOutputTypes OBJECT
}
public calcouttypes Calculate2(字符串jsonList)
{
var jobjects=JsonConvert.DeserializeObject(jsonList);
foreach(jobjects中的var jobject)
{
Type runtimeType=Type.GetType(string.Format(“WCFService.{0}”,jobject.GetValue(“Type”));
var input=jobject.ToObject(runtimeType);//这里我们将jobject转换为刚刚创建运行时的定义类型
//此时,您有一个强类型对象“input”(CalcInputTypes1或CalcInputTypes2或…)
}
return new calcouttypes(){STATUS=“一切正常!!(输入为:异类对象的json数组)”};//这里返回calcouttypes对象
}
您可以避免使用ExpandoObject
而直接使用,如下所示:
var query = from obj in JsonConvert.DeserializeObject<List<JObject>>(jsonList, converter)
let jType = obj["Type"]
where jType != null
let type = Type.GetType(string.Format("WCFService.{0}", (string)jType))
where type != null
where obj.Remove("Type") // Assuming this is a synthetic property added during serialization that you want to remove.
select obj.ToObject(type);
var objs = query.ToList();
另一种可能的解决方案是@dbc在评论中建议使用Newtonsoft.Json方法
JsonConvert.DeserializeObject(Json,type)
,如下所示:
var json = JsonConvert.SerializeObject(input);
Type T = Type.GetType(string.Format("WCFService.{0}", input.Type));
T obj = JsonConvert.DeserializeObject<typeof(T)>(json); // this line fails compilation
private T convertTo<T>(string json)
{
return (T)JsonConvert.DeserializeObject(json, typeof(T));
}
var json = // some serialized json ...
var o = convertTo<MyCustomType>(json);
private T convertTo(字符串json)
{
返回(T)JsonConvert.DeserializeObject(json,typeof(T));
}
var json=//一些序列化的json。。。
var o=convertTo(json);
其中,MyCustomType
是您输入的类型(var inputType=type.GetType(string.Format(“WCFService.{0}”,input.type));
不要忘记隐式强制转换(t)
另一种可能是使用.NET framework内置程序编写您自己的类型转换器。您不需要ExpandoobExt列表,只需使用CustomCreationConverter,如中所述,将所有学分都添加到@JimSan即可
public class Example
{
[Test]
public void Test()
{
var json =
"[\r\n {\r\n \"Name\": \"PLAN-A\",\r\n \"Type\": \"CalcInputTypes1\",\r\n \"CS\": 1.1111,\r\n \"CUSTOM_DATE1\": \"2015-05-22\",\r\n \"CUSTOM_EARN1\": 65500.0,\r\n \"GENDER\": \"Male\"\r\n },\r\n {\r\n \"Name\": \"PLAN-B\",\r\n \"Type\": \"CalcInputTypes2\",\r\n \"CS\": 2.22222,\r\n \"CUSTOM_DATE2\": \"2015-05-23\",\r\n \"CUSTOM_EARN2\": 12000.0,\r\n \"PROVINCE\": \"Ontario\"\r\n }\r\n]";
var result = JsonConvert.DeserializeObject<List<Item>>(json, new JsonItemConverter());
Assert.That(result[0], Is.TypeOf<CalcInputTypes1>());
Assert.That(((CalcInputTypes1)result[0]).Gender, Is.EqualTo("Male"));
Assert.That(result[1], Is.TypeOf<CalcInputTypes2>());
Assert.That(((CalcInputTypes2)result[1]).Province, Is.EqualTo("Ontario"));
}
public class JsonItemConverter : Newtonsoft.Json.Converters.CustomCreationConverter<Item>
{
public override Item Create(Type objectType)
{
throw new NotImplementedException();
}
public Item Create(Type objectType, JObject jObject)
{
var type = (string)jObject.Property("Type");
switch (type)
{
case "CalcInputTypes1":
return new CalcInputTypes1();
case "CalcInputTypes2":
return new CalcInputTypes2();
}
throw new ApplicationException(String.Format("The given type {0} is not supported!", type));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load JObject from stream
var jObject = JObject.Load(reader);
// Create target object based on JObject
var target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
public abstract class Item
{
public string Type { get; set; }
}
public class CalcInputTypes1 : Item
{
[JsonProperty("GENDER")]
public string Gender { get; set; }
}
public class CalcInputTypes2 : Item
{
[JsonProperty("PROVINCE")]
public string Province { get; set; }
}
}
公共类示例
{
[测试]
公开无效测试()
{
var-json=
“[\r\n{\r\n\'Name\”:“PLAN-A\”,\r\n\'Type\”:“Canciputtypes1\”,\r\n\'CS\”:1.1111、\r\n\'CUSTOM\u DATE1\”:“2015-05-22\”,\r\n\'CUSTOM\u EARN1\”:65500.0、\r\n\'性别\:“男性\\r\n\”,\r\r\n\'Name\:“PLAN-B\,\r\n\”,\r\r\n\“Canciputtypes2\”\“:2.22222、\r\n\“海关日期2\”:“2015-05-23\”、\r\n\“海关收入2\”:12000.0、\r\n\“省”:“安大略省”\r\n}\r\n]”;
var result=JsonConvert.DeserializeObject(json,新的JsonItemConverter());
Assert.That(结果[0],是.TypeOf());
断言:((第1类)结果[0])。性别,等于男性;
Assert.That(结果[1],是.TypeOf());
断言:((2)结果[1])省,即安大略省;
}
公共类JSONIMConverter:Newtonsoft.Json.Converters.CustomCreationConverter
{
公共重写项创建(类型objectType)
{
抛出新的NotImplementedException();
}
创建公共项(类型objectType,JObject JObject)
{
变量类型=(字符串)jObject.Property(“类型”);
开关(类型)
{
案例“1”:
返回新的类型1();
案例“2”:
返回新的puttypes2();
}
抛出新的ApplicationException(String.Format(“不支持给定类型{0}!”,type));
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
//从流中加载作业对象
var jObject=jObject.Load(读卡器);
//基于JObject创建目标对象
var target=Create(objectType,jObject);
//填充对象属性
填充(jObject.CreateReader(),目标);
回报目标;
}
}
公共抽象类项
{
公共字符串类型{get;set;}
}
公共类类型1:项
{
[JsonProperty(“性别”)]
公共字符串{get;set;}
}
公共类类型2:项
{
[JsonProperty(“省”)]
公共字符串省{get;set;}
}
}
也许有一些简单的方法可以轻松有效地映射属性,但如果没有,那么您可以通过一点反射来手动进行映射-。然后,您想对确定并转换的类型做什么?列表中是否有一组固定的类型,或者是灵活且动态的类型?重新序列化每个类型将特定的ExpandoObject
转换为json,然后使用或将该json转换为适当的CLR类型,不要使用ExpandoObject
。加载到JObject
数组中,对于每个JObject
,检查并删除type属性,然后执行。可能会重复[使用JSON.NET将异类JSON数组反序列化为协变列表][1][1]:
public class Example
{
[Test]
public void Test()
{
var json =
"[\r\n {\r\n \"Name\": \"PLAN-A\",\r\n \"Type\": \"CalcInputTypes1\",\r\n \"CS\": 1.1111,\r\n \"CUSTOM_DATE1\": \"2015-05-22\",\r\n \"CUSTOM_EARN1\": 65500.0,\r\n \"GENDER\": \"Male\"\r\n },\r\n {\r\n \"Name\": \"PLAN-B\",\r\n \"Type\": \"CalcInputTypes2\",\r\n \"CS\": 2.22222,\r\n \"CUSTOM_DATE2\": \"2015-05-23\",\r\n \"CUSTOM_EARN2\": 12000.0,\r\n \"PROVINCE\": \"Ontario\"\r\n }\r\n]";
var result = JsonConvert.DeserializeObject<List<Item>>(json, new JsonItemConverter());
Assert.That(result[0], Is.TypeOf<CalcInputTypes1>());
Assert.That(((CalcInputTypes1)result[0]).Gender, Is.EqualTo("Male"));
Assert.That(result[1], Is.TypeOf<CalcInputTypes2>());
Assert.That(((CalcInputTypes2)result[1]).Province, Is.EqualTo("Ontario"));
}
public class JsonItemConverter : Newtonsoft.Json.Converters.CustomCreationConverter<Item>
{
public override Item Create(Type objectType)
{
throw new NotImplementedException();
}
public Item Create(Type objectType, JObject jObject)
{
var type = (string)jObject.Property("Type");
switch (type)
{
case "CalcInputTypes1":
return new CalcInputTypes1();
case "CalcInputTypes2":
return new CalcInputTypes2();
}
throw new ApplicationException(String.Format("The given type {0} is not supported!", type));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load JObject from stream
var jObject = JObject.Load(reader);
// Create target object based on JObject
var target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
public abstract class Item
{
public string Type { get; set; }
}
public class CalcInputTypes1 : Item
{
[JsonProperty("GENDER")]
public string Gender { get; set; }
}
public class CalcInputTypes2 : Item
{
[JsonProperty("PROVINCE")]
public string Province { get; set; }
}
}