代码之家  ›  专栏  ›  技术社区  ›  john Gu

如何使用JSON.NET反序列化部分JSON对象

  •  2
  • john Gu  · 技术社区  · 10 年前

    我正在开发一个asp。net mvc web应用程序。我正在接收以下json对象:-

    {  
       "operation":{  
          "name":"GET RESOURCE ACCOUNTLIST",
          "result":{  
             "status":"Success",
             "message":"Resource details with account list fetched successfully"
          },
          "Details":{  
             "RESOURCE ID":"1",
             "RESOURCE NAME":"test resource",
             "RESOURCE DESCRIPTION":"",
             "RESOURCE TYPE":"Windows",
             "DNS NAME":"172.16.20.101",
             "PASSWORD POLICY":"Strong",
             "DEPARTMENT":"",
             "LOCATION":"",
             "RESOURCE URL":"",
             "RESOURCE OWNER":"admin",
             "ACCOUNT LIST":[  
                {  
                   "ISFAVPASS":"false",
                   "ACCOUNT NAME":"root",
                   "PASSWDID":"1",
                   "IS_TICKETID_REQD_MANDATORY":"false",
                   "ISREASONREQUIRED":"false",
                   "AUTOLOGONLIST":[  
                      "Windows Remote Desktop",
                      "Remote Desktop"
                   ],
                   "PASSWORD STATUS":"****",
                   "IS_TICKETID_REQD":"false",
                   "ACCOUNT ID":"1",
                   "AUTOLOGONSTATUS":"User is not allowed to automatically logging in to remote systems in mobile",
                   "IS_TICKETID_REQD_ACW":"false"
                }
             ]
          }
       }
    }
    

    我正在使用JSON。NET来进行反序列化,所以我创建了以下模型类(我没有包含JSON对象接收的所有属性,因为我实际上并不需要所有属性)。

    public class ResourceAccountListInfo
    {
        public Operation2 operation { get; set; }
    }
    
    public class Operation2
    {    
        public string name { get; set; }
        public Result result { get; set; }
        public IList<Details2> Details { get; set; }    
    }
    
    public class Details2
    {     
        [JsonProperty("RESOURCE DESCRIPTION")]
        public string RESOURCEDESCRIPTION { get; set; }
    
        [JsonProperty("RESOURCE NAME")]
        public string RESOURCENAME { get; set; }
    
        [JsonProperty("RESOURCE ID")]
        public string RESOURCEID { get; set; }
    
        [JsonProperty("RESOURCE TYPE")]
        public string RESOURCETYPE { get; set; }
    
        [JsonProperty("DNS NAME")]
        public string DNSNAME { get; set; }
    
        [JsonProperty("ACCOUNT LIST")]
        public IList<ACCOUNTLIST> ACCOUNTLIST { get; set; }
    }
    

    当我尝试使用此语句反序列化json时,会出现以下错误:

      ResourceAccountListInfo resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json); 
    

    错误为:

    Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1[T.ViewModels.Details2]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
    To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
    Path 'operation.Details.['RESOURCE ID']', line 1, position 171
    

    我认为问题是,我的JSON对象中有一些属性在模型类中没有映射,这可能是原因吗?

    2 回复  |  直到 10 年前
        1
  •  2
  •   Matt Burland    10 年前

    这里的错误消息实际上很有指导意义:

    无法将当前JSON对象(例如{“name”:“value”})反序列化为类型“System.Collections.Generic.IList`1[T.ViewModels.Details2]”,因为该类型需要JSON数组(例如[1,2],3])才能正确反序列化。 要修复此错误,请将JSON更改为JSON数组(例如[1,2],3])或更改反序列化类型,使其成为可以从JSON对象反序列化的普通.NET类型(例如,不是像整数这样的基元类型,不是像数组或列表这样的集合类型)。JsonObjectAttribute也可以添加到类型中,以强制其从JSON对象反序列化。 路径操作。详细信息。[“资源ID”]',第1行,位置171

    它告诉你的是它有一个对象,你要求它将其反序列化为一个集合。它不能做到这一点,因为它不是一个集合。

    您的模型中有:

    public IList<Details2> Details { get; set; }
    

    但相应的 details json中的属性是:

      "Details":{  
         "RESOURCE ID":"1",
         "RESOURCE NAME":"test resource",
         "RESOURCE DESCRIPTION":"",
         "RESOURCE TYPE":"Windows",
         "DNS NAME":"172.16.20.101",
         "PASSWORD POLICY":"Strong",
         "DEPARTMENT":"",
         "LOCATION":"",
         "RESOURCE URL":"",
         "RESOURCE OWNER":"admin",
         "ACCOUNT LIST":[  
            {  
               "ISFAVPASS":"false",
               "ACCOUNT NAME":"root",
               "PASSWDID":"1",
               "IS_TICKETID_REQD_MANDATORY":"false",
               "ISREASONREQUIRED":"false",
               "AUTOLOGONLIST":[  
                  "Windows Remote Desktop",
                  "Remote Desktop"
               ],
               "PASSWORD STATUS":"****",
               "IS_TICKETID_REQD":"false",
               "ACCOUNT ID":"1",
               "AUTOLOGONSTATUS":"User is not allowed to automatically logging in to remote systems in mobile",
               "IS_TICKETID_REQD_ACW":"false"
            }
         ]
      }
    

    这是一个对象(注意大括号 {} ).

    所以你需要做的就是改变你的 Details 属性:

    public Details2 Details { get; set; }
    

    json中的任何属性 细节 中没有相应属性 Details2 将被默默忽略。所以你 不需要映射json中的每个属性 只画出你真正关心的那些。

        2
  •  0
  •   Andrei    10 年前

    您可以使用 JObject 具有 dynamic :

    dynamic json = JObject.Parse(jsonString);
    

    然后按照您想要的方式填充模型,而不创建整个类层次结构:

    var operationName = json.operation.name;
    

    请注意:带有 动态 您的属性是在运行时创建的。这意味着您将没有智能感知支持,如果您尝试调用不存在的方法或属性,您将得到运行时异常。因此,使用这种方法时要非常小心。