-1

Sending a WebClient() request to a Web API, my API call is returning with data which I am deserialising with JsonConvert.DeserializeObject().

The object then has properties which I cannot seem to reference.

var coursesParams = new NameValueCollection();

coursesParams.Add("grant_type", "password");
coursesParams.Add("client_id", "ContentUpload");
coursesParams.Add("client_secret", "2dfe381b4e620fff9b4fa05997e26d141d9c2c6d");
coursesParams.Add("username", "isadmin");
coursesParams.Add("password", "xxxxxxxxx");

WebClient coursesRequest = new WebClient();

coursesRequest.Encoding = Encoding.UTF8;
coursesRequest.Headers.Add("Authorization", "Bearer " + x.access_token);
coursesRequest.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
coursesRequest.Headers.Add("Accept-Language", "en-US");
coursesRequest.Headers.Add("Accept", "text/html, application/xhtml+xml, */*");
coursesRequest.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");

var coursesData = coursesRequest.UploadValues("https://xxx.yyyyyyyyyy.com/api/course/courses", "POST", coursesParams);

var y = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(coursesData));

System.Console.ReadKey();

When I pause the program and examine the y object in the debugger, it shows properties, but I cannot reference any of them. Screen image:

enter image description here

enter image description here

And, any attempt to reference (or read) these properties results in an error:

y.ChildrenTokens
error CS1061: 'object' does not contain a definition for 'ChildrenTokens' and no accessible extension method 'ChildrenTokens' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
y.Count
error CS1061: 'object' does not contain a definition for 'Count' and no accessible extension method 'Count' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

What am I doing (or seeing) wrong? Are these properties simply not accesssible? Or am I referencing them incorrectly?

KWallace
  • 624
  • 7
  • 15

1 Answers1

0

In C#, you can't access properties that are not defined on a type. You can see the properties in the debugger because that is the raw text input. But since you did not specify a type to deserialize to, the DeserializeObject method is simply creating plain object instances - and object does not contain definitions for any of your properties (ChildrenTokens, Count, etc).

To fix this, you should create a class with properties that match the schema of the JSON that you are parsing. This might be a good start:

public class CourseData {
    public List<Course> courses { get; set; }
    public string item_count { get; set; }
    public bool success { get; set; }
}
public class Course {
    public int course_id { get; set; }
    public string code { get; set; }
    public string course_name { get; set; }
}

Fill in the remaining properties, and then deserialize like this:

// Option 1
var y = JsonConvert.DeserializeObject<CourseData>(Encoding.ASCII.GetString(coursesData));

// Option 2
CourseData y = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(coursesData));
acomputerdog
  • 194
  • 1
  • 8
  • I kinda thought it was going to go that way. And in other instances, I have done that. However, this JSON contains multiple objects within itself, and I do not know how to make a class that it could deserialise into. {{ "courses": [ {"course_id": 1, "code": "ORG HR"}, {"course_id": 2, "code": "ORG HR S"}, {"course_id": 3,"code": "ORG GHS",}, {"course_id": 4,"code": "SAF"} ], "item_count": "72", "success": true }} – KWallace Jan 13 '21 at 21:38
  • Sorry, that won't format well in a comment, but you can see the repeating group inside the json object – KWallace Jan 13 '21 at 21:39
  • @KirbyL.Wallace That's what the `List courses` is for in my example. The JSON deserializer will convert each of the nested objects into a `Course` and then store them all in a `List` object. You can access them via `courses[index]`. – acomputerdog Jan 13 '21 at 21:43
  • I did find this. And it looks exactly like what I need to do. https://stackoverflow.com/questions/38793151/deserialize-nested-json-into-c-sharp-objects – KWallace Jan 13 '21 at 21:43
  • 1
    @KirbyL.Wallace That will work, however that technique is best used (in C#, at least) for cases where the property names ("courses", "course_id", etc) can change. In other cases, you should define classes in order to benefit from static typing. EDIT: "that" referring to the use of `IDictionary` in the accepted answer of the linked thread. – acomputerdog Jan 13 '21 at 21:45
  • Yep, I did. I created classes and deserialsed into them and it works fine. Thanks for pointing that out. – KWallace Jan 21 '21 at 02:50