将json字符串序列化为c#对象时出现问题
我有一个调用webservice的类,它返回一个JSON字符串,我需要将该字符串反序列化为C#对象。我成功地做到了这一点;然而,我遇到了一个情景,我不确定确切地说是最好的处理方式。更具体地说,JSON要么返回将json字符串序列化为c#对象时出现问题,c#,json,serialization,C#,Json,Serialization,我有一个调用webservice的类,它返回一个JSON字符串,我需要将该字符串反序列化为C#对象。我成功地做到了这一点;然而,我遇到了一个情景,我不确定确切地说是最好的处理方式。更具体地说,JSON要么返回列表,要么只返回列表。如果我的对象是List,而JSON是List,那么我在反序列化时遇到问题。在这种情况下,将引发异常 这是我正在尝试反序列化的类: public class WorkOrderJson { public string type { get;
列表
,要么只返回列表
。如果我的对象是List
,而JSON是List
,那么我在反序列化时遇到问题。在这种情况下,将引发异常
这是我正在尝试反序列化的类:
public class WorkOrderJson
{
public string type { get; set; }
public Properties properties { get; set; }
public Geometry geometry { get; set; }
}
public class Properties
{
public string FeatureType { get; set; }
public string WorkOrderID { get; set; }
public string EqEquipNo { get; set; }
}
对于Geometry类,返回的坐标是上面的问题。如果返回的JSON是一个列表
,则可以进行序列化
public class Geometry
{
public string type { get; set; }
public List<List<double>> coordinates { get; set; }
}
下面是列表的一个示例:
如果我理解并且您试图将列表
反序列化为列表
,则应该会出错。您告诉它将其反序列化为与序列化之前不同的内容。我建议您传播它与字符串在一起的一些指示,以便您可以检查并反序列化为该类型,或者包装反序列化尝试,然后try
一个,如果失败,则包装另一个
每次更新编辑
public class WorkOrderJson<T>
{
public Geometry<T> geometry { get; set; }
public WorkOrderJson<List<T>> Promote()
{
var temp = new WorkOrderJson<List<T>>();
temp.geometry = geometry.Promote();
return temp;
}
}
public class Geometry<T>
{
public T coordinates { get; set; }
public Geometry<List<T>> Promote()
{
var temp = new Geometry<List<T>>();
temp.coordinates = new List<T>(){ coordinates };
return temp;
}
}
public List<WorkOrder<List<List<double>>>> Deserialize(string x)
{
try
{
return new JavaScriptSerializer().Deserialize<List<WorkOrderJson<List<List<double>>>>>(x);
}
catch(InvalidOperationException ex)
{
return new JavaScriptSerializer().Deserialize<List<WorkOrderJson<List<double>>>>(x).Select(workOrder => workOrder.Promote());
}
}
public class WorkOrderJson
{
公共几何体{get;set;}
公共工作促进
{
var temp=新的WorkOrderJson();
temp.geometry=geometry.Promote();
返回温度;
}
}
公共课几何
{
公共T坐标{get;set;}
公共几何推广()
{
var temp=新几何体();
temp.coordinates=新列表(){coordinates};
返回温度;
}
}
公共列表反序列化(字符串x)
{
尝试
{
返回新的JavaScriptSerializer();
}
捕获(无效操作异常ex)
{
返回新的JavaScriptSerializer();
}
}
因此,对于任何关心将几何体类更改为以下内容的人,我的问题已经得到了解决:
public class Geometry
{
public string type { get; set; }
public object coordinates { get; set; }
}
刚刚将列表更改为对象。然后在运行时,我可以检查对象是列表列表还是仅仅是列表,然后继续操作。创建一个自定义对象,并将其注册到JavaScriptSerializer
然后,您将进行如下反序列化:
var converter = new JavaScriptSerializer();
converter.RegisterConverters(new List<JavaScriptConverter>() {new GeometryConverter()});
var workOrderJson = converter.Deserialize<List<WorkOrderJson>>(response);
var converter=newJavaScriptSerializer();
registerConverter(新列表(){new GeometryConverter()});
var workOrderJson=转换器。反序列化(响应);
这个转换器可以工作:
public class GeometryConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>(new Type[] {typeof(Geometry)}); }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Geometry geometry = obj as Geometry;
if (geometry != null)
{
// Create the representation
var result = new Dictionary<string, object>();
if (geometry.coordinates.Count == 1)
{
result.Add("type", "Point");
result.Add("coordinates", geometry.coordinates[0]);
}
else if (geometry.coordinates.Count > 1)
{
result.Add("type", "LineString");
result.Add("coordinates", geometry.coordinates);
}
return result;
}
return new Dictionary<string, object>();
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
Geometry geometry = null;
if (type == typeof(Geometry))
{
geometry = new Geometry();
geometry.type = (string)dictionary["type"];
geometry.coordinates = new List<List<double>>();
if ( geometry.type == "Point")
{
ArrayList arrayList = (ArrayList)dictionary["coordinates"];
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
else if (geometry.type == "LineString")
{
geometry.type = "LineString";
ArrayList coordinatesList = (ArrayList)dictionary["coordinates"];
foreach (ArrayList arrayList in coordinatesList)
{
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
}
}
return geometry;
}
private List<double> ConvertCoordinates(ArrayList coordinates)
{
var list = new List<double>();
foreach (var coordinate in coordinates)
{
list.Add((double)System.Convert.ToDouble(coordinate));
}
return list;
}
}
公共类GeometryConverter:JavaScriptConverter
{
公共覆盖IEnumerable SupportedTypes
{
获取{返回新列表(新类型[]{typeof(几何体)});}
}
公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序)
{
几何体=作为几何体的obj;
如果(几何体!=null)
{
//创建表示
var result=newdictionary();
if(geometry.coordinates.Count==1)
{
结果。添加(“类型”、“点”);
结果。添加(“坐标”,几何。坐标[0]);
}
如果(geometry.coordinates.Count>1),则为else
{
结果。添加(“类型”、“行字符串”);
结果。添加(“坐标”,几何。坐标);
}
返回结果;
}
返回新字典();
}
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
if(dictionary==null)
抛出新的ArgumentNullException(“字典”);
几何=空;
if(类型==类型(几何体))
{
几何体=新几何体();
geometry.type=(字符串)字典[“type”];
geometry.coordinates=新列表();
如果(geometry.type==“点”)
{
ArrayList ArrayList=(ArrayList)字典[“坐标”];
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
else if(geometry.type==“LineString”)
{
geometry.type=“LineString”;
ArrayList coordinates List=(ArrayList)字典[“坐标”];
foreach(协调列表中的ArrayList ArrayList)
{
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
}
}
返回几何;
}
私有列表坐标(ArrayList坐标)
{
var list=新列表();
foreach(坐标中的变量坐标)
{
list.Add((双)System.Convert.ToDouble(坐标));
}
退货清单;
}
}
是的,我同意,它应该会失败,但问题是json返回字符串是list(list(object))和list(object)的“坐标”,所以当我不知道返回是list(list(object))还是list(object)时,如何创建Geometry类。问题是如何处理这两个问题?@Maxqueue通过您的更新,我更了解问题所在。看起来您找到了解决方案,但另一种方法是参数化WorkOrder
(和Geometry
),使其成为WorkOrder
或WorkOrder
尝试
反序列化为第一个,如果失败,则反序列化为第二个。但是,在返回时(一个元素的列表),您需要将列表
案例“升级”为列表
,因此它们是相同的类型。但是,您将有两个同名变量。@Maxqueue我用我建议的示例更新了答案。它并不漂亮,它是否值得取决于您的用例。但是,让一个裸露的对象
四处浮动,并且可能需要打开它是列表
还是列表
也不是很吸引人。这个工具很好,只需粘贴你的
public class Geometry
{
public string type { get; set; }
public object coordinates { get; set; }
}
var converter = new JavaScriptSerializer();
converter.RegisterConverters(new List<JavaScriptConverter>() {new GeometryConverter()});
var workOrderJson = converter.Deserialize<List<WorkOrderJson>>(response);
public class GeometryConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>(new Type[] {typeof(Geometry)}); }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Geometry geometry = obj as Geometry;
if (geometry != null)
{
// Create the representation
var result = new Dictionary<string, object>();
if (geometry.coordinates.Count == 1)
{
result.Add("type", "Point");
result.Add("coordinates", geometry.coordinates[0]);
}
else if (geometry.coordinates.Count > 1)
{
result.Add("type", "LineString");
result.Add("coordinates", geometry.coordinates);
}
return result;
}
return new Dictionary<string, object>();
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
Geometry geometry = null;
if (type == typeof(Geometry))
{
geometry = new Geometry();
geometry.type = (string)dictionary["type"];
geometry.coordinates = new List<List<double>>();
if ( geometry.type == "Point")
{
ArrayList arrayList = (ArrayList)dictionary["coordinates"];
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
else if (geometry.type == "LineString")
{
geometry.type = "LineString";
ArrayList coordinatesList = (ArrayList)dictionary["coordinates"];
foreach (ArrayList arrayList in coordinatesList)
{
geometry.coordinates.Add(ConvertCoordinates(arrayList));
}
}
}
return geometry;
}
private List<double> ConvertCoordinates(ArrayList coordinates)
{
var list = new List<double>();
foreach (var coordinate in coordinates)
{
list.Add((double)System.Convert.ToDouble(coordinate));
}
return list;
}
}