C# 如何序列化3种对象类型中的任何一种,其中一种包含抽象类?
我正在通过网络发送3个.net对象:C# 如何序列化3种对象类型中的任何一种,其中一种包含抽象类?,c#,.net,json.net,C#,.net,Json.net,我正在通过网络发送3个.net对象: - List<int> - List<ParentObject> - string 我想根据接收到的3个对象调用3个不同的函数 Object genericObject = JsonConvert.DeserializeObject(message, new JsonSerializerSettings { TypeNameHandling = TypeNameHandl
- List<int>
- List<ParentObject>
- string
我想根据接收到的3个对象调用3个不同的函数
Object genericObject = JsonConvert.DeserializeObject(message, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
if (genericObject is List<int>)
{
List<int> myList= (List<int>)genericObject;
myfunction1(myList);
}
if (genericObject is List<ParentObject>)
{
//etc..
Object genericObject=JsonConvert.DeserializeObject(消息,新的JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.Auto
});
如果(genericObject是列表)
{
列表myList=(列表)genericObject;
myfunction1(myList);
}
如果(genericObject是列表)
{
//等等。。
ParentObject导致DeserializeObject()出现问题,因为它说“无法创建ParentObject类型的实例。type是接口或抽象类,无法实例化”。因此我想我可能需要在
这仍然不能解决我的问题,因为CustomCreationConverter在反序列化期间需要类型,而我在反序列化之后才检查类型
有什么解决问题的建议吗?如果我使用这样定义的对象:
public enum EntityType { Child1, Child2 };
abstract class ParentObject
{
public EntityType et { get; set; }
}
class ChildClass : ParentObject
{
public int ChildClassProp { get; set; }
public ChildClass()
{
this.et = EntityType.Child1;
}
}
class ChildClass2 : ParentObject
{
public int ChildClass2Prop { get; set; }
public ChildClass2()
{
this.et = EntityType.Child2;
}
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
};
List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });
string message = JsonConvert.SerializeObject(list,
Newtonsoft.Json.Formatting.Indented, JSsettings);
list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
{
"$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
"ChildClassProp": 1,
"et": 0
},
{
"$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
"ChildClass2Prop": 2,
"et": 1
}
]
{
"$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
"$values": [
{
"ChildClassProp": 1,
"et": 0
},
{
"ChildClass2Prop": 2,
"et": 1
}
]
}
然后我可以愉快地将派生类(ChildClass
和ChildClass2
)反序列化为ParentObject
,如下所示:
public enum EntityType { Child1, Child2 };
abstract class ParentObject
{
public EntityType et { get; set; }
}
class ChildClass : ParentObject
{
public int ChildClassProp { get; set; }
public ChildClass()
{
this.et = EntityType.Child1;
}
}
class ChildClass2 : ParentObject
{
public int ChildClass2Prop { get; set; }
public ChildClass2()
{
this.et = EntityType.Child2;
}
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
};
List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });
string message = JsonConvert.SerializeObject(list,
Newtonsoft.Json.Formatting.Indented, JSsettings);
list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
{
"$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
"ChildClassProp": 1,
"et": 0
},
{
"$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
"ChildClass2Prop": 2,
"et": 1
}
]
{
"$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
"$values": [
{
"ChildClassProp": 1,
"et": 0
},
{
"ChildClass2Prop": 2,
"et": 1
}
]
}
其中的关键是使用typenameholling=typenameholling.Auto
进行序列化和反序列化。使用typenameholling.Arrays
创建如下消息:
public enum EntityType { Child1, Child2 };
abstract class ParentObject
{
public EntityType et { get; set; }
}
class ChildClass : ParentObject
{
public int ChildClassProp { get; set; }
public ChildClass()
{
this.et = EntityType.Child1;
}
}
class ChildClass2 : ParentObject
{
public int ChildClass2Prop { get; set; }
public ChildClass2()
{
this.et = EntityType.Child2;
}
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
};
List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });
string message = JsonConvert.SerializeObject(list,
Newtonsoft.Json.Formatting.Indented, JSsettings);
list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
{
"$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
"ChildClassProp": 1,
"et": 0
},
{
"$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
"ChildClass2Prop": 2,
"et": 1
}
]
{
"$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
"$values": [
{
"ChildClassProp": 1,
"et": 0
},
{
"ChildClass2Prop": 2,
"et": 1
}
]
}
请注意,列表项的类型不包括在内,只包括列表的类型,因此会出现错误
编辑:
我认为最简单的方法就是定义一个简单的类,像这样的类,作为序列化对象的薄包装器:
class ObjectContainer
{
public object Data { get; set; }
}
然后代码将如下所示(注意对typenameholling.Auto
的更改):
JsonSerializerSettings JSsettings=新的JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.Auto
};
列表=新列表();
添加(new ChildClass(){ChildClassProp=1});
添加(新的ChildClass2(){ChildClass2Prop=2});
ObjectContainer=newObjectContainer()
{
数据=列表
};
string message=JsonConvert.SerializeObject(容器,
Newtonsoft.Json.Formatting.Indented,JSsettings);
var objectContainer=JsonConvert.DeserializeObject(消息,JSsettings);
if(objectContainer.Data为列表)
{
Write(“objectContainer.Data是List”);
}
else if(objectContainer.Data为列表)
{
Write(“objectContainer.Data是List”);
}
else if(objectContainer.Data为字符串)
{
Write(“objectContainer.Data是字符串”);
}
我采用这种方法的原因是,Json.Net将负责几乎所有的工作。只需调用非泛型的
JsonConvert.DeserializeObject
方法就可以了,但是您需要做额外的工作,因为该方法返回的是JContainer
,而不是对象
,我不能使用行列表=JsonConvert.DeserializeObject(message,JSsettings);
因为我不知道将接收3种对象类型中的哪一种。我必须在不知道类型的情况下进行反序列化,然后在中检查该类型。否则,将其转换为该类型并调用相应的函数。