Search code examples
c#arraysjsondropboxdesire2learn

Newtonsoft.Json.Linq.JArray.Parse(string)' has some invalid arguments


I am trying to extract data from D2L for the dropbox submissions using API's I have a link which returns a Json Array as per told on the documentation and from this Array I just need the Id feild nothing else.

I have tried to convert this Array into dynamic Object but that didn't help.

Here is my code.

var client = new RestClient("https://" + LMS_URL);
var authenticator = new ValenceAuthenticator(userContext);
string Link = "/d2l/api/le/1.12/UnitID/dropbox/folders/UniID/submissions/";
var request = new RestRequest(string.Format(Link));
request.Method = Method.GET;

authenticator.Authenticate(client, request);

var response = client.Execute(request);

string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(response.Content);
Response.Write(jsonString);

//var splashInfo = JsonConvert.DeserializeObject<ObjectD>(response.Content);
 dynamic jsonResponse = JsonConvert.DeserializeObject(response.Content);

var parsedObject = jsonResponse.Parse(jsonResponse);
string json = jsonResponse;
var popupJson = parsedObject["id"].ToString();

What my goal is that grab the list of ID's from this response and loop through them, these ID's are the key for my next API route.

Here is a glance at what I get from the response:

[
  {
    "Id": 2021,
    "CategoryId": null,
    "Name": "Graded Assignment:  Part 1",
    "CustomInstructions": {
      "Text": "Directions:\r\nCOMPLETE the following TestOut Activities\r\n\r\n1.2.10 Practice Questions\r\n1.3.8 Practice Questions\r\n\r\nGo to TestOut to complete the Assignment."
      //Other properties omitted
    }
    //Other properties omitted
  }
]

Solution

  • The outermost container in the JSON returned is an array, so you need to deserialize to a collection type as specified in the Newtonsoft's Serialization Guide: IEnumerable, Lists, and Arrays.

    Since you only care about the Id property of the object(s) in the array, you can use JsonConvert.DeserializeAnonymousType to deserialize just the interesting value(s):

    var ids =  JsonConvert.DeserializeAnonymousType(response.Content, new [] { new { Id = default(long) } })
        .Select(o => o.Id)
        .ToList();
    

    And if you are certain the outermost array will contain exactly one item, you can do:

    var id =  JsonConvert.DeserializeAnonymousType(response.Content, new [] { new { Id = default(long) } })
        .Select(o => o.Id)
        .Single();
    

    Alternatively, if you think you will later need to deserialize additional properties, you could make an explicit data model as follows:

    public class ObjectId
    {
        public long Id { get; set; }
    }
    

    And do:

    var ids =  JsonConvert.DeserializeObject<List<ObjectId>>(response.Content)
        .Select(o => o.Id)
        .ToList();
    

    Notes:

    • You will need to determine from the API documentation whether long or int is more appropriate for the Id value.

    • As a general rule I recommend not parsing to dynamic because you lose compile-time checking for correctness. When dealing with completely free-form JSON, parsing to JToken may be a better solution -- but your JSON appears to have a fixed schema, so neither is necessary.

    Demo fiddle here.