John John
John John

Reputation: 1

how to deserialize part of the JSON object using JSON.NET

I am working on an asp.net mvc web application. and i am receiving the following json object :-

{  
   "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"
            }
         ]
      }
   }
}

I am using JSON.NET to do the deserilization, so I created the following model classes (I did not include all the properties received by the JSON object since I do not really need all of them).

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; }
}

I am getting the following error when I try to deserialize json using this statement:

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

Error is :

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

I think the problem is that there are some properties inside my JSON object which do not have a mapping inside the model classes, could this be a reason?

Upvotes: 2

Views: 884

Answers (2)

Matt Burland
Matt Burland

Reputation: 45135

The error message here is actually pretty instructive:

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) 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

What it's telling you is that it has an object and you have asked it to deserialize it as a collection. It can't do that, because it isn't a collection to start with.

You have in your model:

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

But the corresponding details property in your json is:

  "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"
        }
     ]
  }

Which is an object (note the curly braces {}).

So all you need to do is change your Details property to:

public Details2 Details { get; set; }

Any properties in your json details that don't have a corresponding property in Details2 will be silently ignored. So you don't need to map every property from your json only map the ones you actually care about.

Upvotes: 2

Andrei
Andrei

Reputation: 44600

You can use JObject with dynamic:

dynamic json = JObject.Parse(jsonString);

And then populate your model the way you want, without creating the whole class hierarchy:

var operationName = json.operation.name;

Please notice: with dynamic your properties get created in runtime. It means that you will not have intellisense support and if you try to call method or property that doesn't exist you will get a runtime exception. So, be very careful with this approach.

Upvotes: 0

Related Questions