用.NET反序列化JSON以使用对象(非特定类型)内部字段键入

用.NET反序列化JSON以使用对象(非特定类型)内部字段键入,.net,json,oop,.net,Json,Oop,相关问题:(但这是针对JSON.NET的) 是否有标准或推荐的反序列化方法,如: { "command" : "register_user", "params" : { "@c" : "register_params", "name" : "sdfsd", "email" : "sdfsd@ddkdk", "password" : "JDFffJJJd", "address" : { "postcode" : "12345",

相关问题:(但这是针对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"
    }
  }
}
如果我们告诉反序列化程序需要
消息
类型:

class Message
{
  string Command;
  object[] params;
}
似乎没有一个JSON反序列化框架(或其中的文档)可以处理这种情况

  • 也许有一个或大多数框架只是扫描程序集中加载的类型以找到最接近的类型
  • 也许在JSON标准中有一个标准字段类型可以帮助反序列化程序选择正确的类型
  • 也许除了手动(在JSON字符串和反序列化器逻辑中)包含这样的帮助程序之外,没有其他选择了
  • 谢谢

    更新


    对于这里的这个特定示例,隐含的用法是RPC。在我的RPC解决方案中,需要将服务器对象绑定到RPC系统,并且每个RPC方法的MethodInfo都会被缓存—因此每个参数的类型确实可以从MethodInfo输入JSON反序列化器。然而,这个问题仍然是相关的,例如,如果图形变得更深,对象更复杂,那么即使这样也不够。此外,我确信这个问题已经/将会/将会在RPC案例之外遇到。所有的答案可能都很新颖,我只会选择我认为最好的解决方案。

    您可以将自定义的
    SerializationBinder
    与JSON.NET和
    $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; }
        }
    }
    
    消息
    类:

    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);
    
    var设置=新的JsonSerializerSettings
    {
    Binder=新的TypeNameSerializationBinder(“FooBar.{0},BarBaz”),
    TypeNameHandling=TypeNameHandling.All
    };
    字符串json=。。。
    var message=JsonConvert.DeserializeObject(json,设置);
    Assert(message.Params是Person);