【问题标题】:JsonConvert.DeserializeObject in C# when only the string name of the desired object is known当只知道所需对象的字符串名称时,C# 中的 JsonConvert.DeserializeObject
【发布时间】:2016-08-12 12:12:44
【问题描述】:

假设有关文档的信息存储在条形码中,并且信息的结构根据文档类型而有所不同。但是事先不知道文件的类型;条形码告诉我们我们正在处理什么样的文件:

条形码值不会像这样存储分隔字符串:

author|date|subject
author|date|subject|approvedby1;approvedby2

但将包含 json 表示法:

 FOO|{"author": "Smokey", "date": "01/01/2015", "subject": "widgets"}

 GOO|{"author": "Smokey", "date": "01/01/2015", "subject": "widgets", "approvals": ["Mike","Jane"]}

当我们获取条形码文本数据时,我们从| 分隔符左侧的值看到我们需要实例化FOOGOO。我们抓取| 右侧的字符串并将其提供给JsonConvert

如何告诉JsonConvert.DeserializeObject<some type> 从它的 json 表示中返回一个 GOO 对象?

  var myGoo = JsonConvert.DeserializeObject<?>(jsonStringGOO)

尖括号&lt; &gt;之间是什么?

编辑:理想情况下,不使用 switch 语句。

假设当前命名空间包含所有可能类型的类定义。

【问题讨论】:

    标签: c# json reflection


    【解决方案1】:

    如何尝试使用反射获取程序集的类型

    var data = input.Split('|');
    
    var assembly = Assembly.LoadFrom("MyDll.dll");
    
    var myType = assembly.GetType("My.Namespace." + data[0]); // GOO / BAR / etc
    
    JsonConvert.DeserializeObject(data[1], myType)
    

    Assembly.GetType(string name)

    JsonConvert.DeserializeObject(string value, Type type)

    注意对于调试,您可以使用这样的代码获取类型的全名

    var t = typeof(Goo);
    Debug.WriteLine(t.FullName);
    

    【讨论】:

    • 我很少使用反射,并且在 Assembly.GetType 行上出现错误,提示 an object reference is required for the non-static field, method, or property Assembly.GetType(string)。必须实例化什么反射对象?
    • 谢谢。 “MyAssembly”后面的引号是在引号里面还是外面?我认为+ "." + 是这样吗?
    • 对不起 - 另一个错字。应该在里面
    • 我正在尝试 Assembly assm=Assembly.GetExecutingAssembly(); var myType=assm.GetType(assm.GetName() + ".Test.GOO");myType 为空。在当前正在执行的程序集中的命名空间Test 中找到类GOO
    • 当我删除 assm.GetName() 并仅提供类型的 FullName 时,会分配 myType。取得进展。谢谢!
    【解决方案2】:

    假设您有一个名为GOO 的类,则调用的类型位于方括号之间。但是你必须根据类型进行切换:

    class GOO {
      string author { get; set; }
      string date { get; set; }
      // ...
    }
    
    class FOO { 
      // ...
    }
    
    object parse(string barcode) {
      int pos = barcode.IndexOf('|');
      string type = barcode.substring(0,pos);
      string obj = barcode.substring(pos+1);
      switch(type) {
       case "GOO": return JsonConvert.DeserializeObject<GOO>(obj);
       case "FOO": return JsonConvert.DeserializeObject<FOO>(obj); 
       default: return null; // unknown type
      }
    }
    

    【讨论】:

    • 有没有办法在没有 switch 语句的情况下做到这一点?我将编辑我的问题。
    • 您还可以使用反射按名称查询类型并使用该类型信息构建通用方法。这无需 switch 语句等即可工作,并且无需重新编译即可扩展
    【解决方案3】:

    你真的需要不同的对象吗?

    因为您可以使用具有所有可能属性的单个对象,并且未接收到的属性将被填充为空白(或为假)。

    我尝试在接收 json 的应用上添加List&lt;string&gt; 属性,效果是该属性具有空值。

    【讨论】:

      【解决方案4】:

      我相信this可以帮到你:只需获取类型名称,通过反射获取类型实例并将其放入泛型类型中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-04
        • 2015-10-09
        • 2011-10-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多