相关问题:JSON.NET - deserialize JSON into object, which class type is in inner field(但这个特定于JSON.NET)
是否有标准或推荐的方式来反序列化:
{
"command" : "register_user",
"params" : {
"@c" : "register_params",
"name" : "sdfsd",
"email" : "sdfsd@ddkdk",
"password" : "JDFffJJJd",
"address" : {
"postcode" : "12345",
"street" : "cherry st",
"number" : "44432",
"country" : "antarctica"
}
}
}
如果我们告诉解串器期望Message
类型:
class Message
{
string Command;
object[] params;
}
似乎没有一个JSON反序列化框架(或一个文档),它可以处理这种情况。
由于
更新
对于此处的此特定示例,隐含用途适用于RPC。在我的RPC解决方案中,需要将服务器对象绑定到RPC系统,并且每个RPC方法的MethodInfo都被缓存 - 因此每个参数的类型确实可以从MethodInfo输入到JSON反序列化器中。然而,这个问题仍然是相关的,例如,如果图形变得更深,具有更复杂的对象,那么即使这样也是不够的。此外,我确信在RPC案例之外已经/将要遇到此问题。所有答案都可能是新颖的,我只会选择我认为 best 的解决方案。
答案 0 :(得分:1)
您可以使用带有JSON.NET和SerializationBinder
属性的自定义$type
。
我们举一个例子:
public class TypeNameSerializationBinder : SerializationBinder
{
public string TypeFormat { get; private set; }
public TypeNameSerializationBinder(string typeFormat)
{
TypeFormat = typeFormat;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.Name;
}
public override Type BindToType(string assemblyName, string typeName)
{
var resolvedTypeName = string.Format(TypeFormat, typeName);
return Type.GetType(resolvedTypeName, true);
}
}
现在让我们假设你有以下JSON:
{
"command" : "register_user",
"params" : {
"$type" : "Person",
"name" : "sdfsd",
"email" : "sdfsd@ddkdk",
"password" : "JDFffJJJd",
"address" : {
"postcode" : "12345",
"street" : "cherry st",
"number" : "44432",
"country" : "antarctica"
}
}
}
并且BarBaz
程序集中包含以下模型:
namespace FooBar
{
public class Person
{
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Postcode { get; set; }
public string Street { get; set; }
public string Number { get; set; }
public string Country { get; set; }
}
}
和Message
班级:
public class Message
{
public string Command { get; set; }
public object Params { get; set; }
}
你可以这样反序列化:
var settings = new JsonSerializerSettings
{
Binder = new TypeNameSerializationBinder("FooBar.{0}, BarBaz"),
TypeNameHandling = TypeNameHandling.All
};
string json = ...
var message = JsonConvert.DeserializeObject<Message>(json, settings);
Debug.Assert(message.Params is Person);