Search code examples
jsonvb.netapijson.netrest-client

Read REST API JSON reply


I have been searching the web back an forth but couldn't find a hint to my issue.

I'm calling a REST API via RestSharp Client. I retrieve a response like this:

{
 "meta": {
  "query_time": 0.007360045,
  "pagination": {
   "offset": 1,
   "limit": 100,
   "total": 1
  },
  "powered_by": "device-api",
  "trace_id": "a0d33897-5f6e-4799-bda9-c7a9b5368db7"
 },
 "resources": [
  "1363bd6422274abe84826dabf20cb6cd"
 ],
 "errors": []
}

I want to query the value of resources at the moment. This is the code I use:

Dim id_request = New RestRequest("/devices/queries/devices/v1?filter=" + filter, Method.GET)
id_request.AddHeader("Accept", "application/json")
id_request.AddHeader("Authorization", "bearer " + bearer)
Dim data_response = data_client.Execute(id_request)
Dim data_response_raw As String = data_response.Content
Dim raw_id As JObject = JObject.Parse(data_response_raw)
Dim id = raw_id.GetValue("resources").ToString

Unfortunately, I'm only getting ["1363bd6422274abe84826dabf20cb6cd"] as a reply instead of 1363bd6422274abe84826dabf20cb6cd

Can anyone point me into the right direction?

I have also tried to deserialize using JsonConvert.DeserializeObject() but I somehow fail.

I found this solution here but if I try to rebuild it fails as it doesn't recognize the Dictionary part

 Dim tokenJson = JsonConvert.SerializeObject(tokenJsonString)
 Dim jsonResult = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jsonString)
 Dim firstItem = jsonResult.Item("data").Item(0)

EDIT:

When trying to deserialize the root as suggested but seems as if the 2nd response is nested JSON.

I have a reply like:

dr = {
     "meta": {
      "query_time": 0.004813129,
      "powered_by": "device-api",
      "trace_id": "5a355c86-37f7-416d-96c4-0c8796c940fc"
     },
     "resources": [
      {
       "device_id": "1363bd6422274abe84826dabf20cb6cd",
       "policies": [
        {
         "policy_type": "prevention",
         "policy_id": "1d34205a4e2c4d1991431c037c8e5734",
         "applied": true,
         "settings_hash": "7cb00a74",
         "assigned_date": "2021-02-22T13:56:37.759459481Z",
         "applied_date": "2021-02-22T13:57:19.962692301Z",
         "rule_groups": []
        }
       ],
       "meta": {
        "version": "352"
       }
      }
     ],
     "errors": []
    }

and I tried:

Dim restApiResponse = JsonConvert.DeserializeObject(Of RestApiResponseRoot)(dr)
' This is your array of strings
Dim resources = restApiResponse.Resources

Unfortunately I get Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {. Path 'resources', line 8, position 3.'


Solution

  • The resources Property is an array. As usual, you need to specify which element of the array you want to consider. In this case, the first one, i.e., the element at index 0.

    Dim jsonObject = JObject.Parse(data_response_raw)
    Dim firstResource = jsonObject("resources")(0).ToString()
    

    If you instead want the array content as a String array, not just the first element - assuming resources could contain more than one string (it's an array after all) - deserialize to String():

    Dim jsonObject = JObject.Parse(data_response_raw)
    Dim resources = JsonConvert.DeserializeObject(Of String())(jsonObject("resources").ToString())
    

    In case you need the whole JSON response, I suggest to deserialize to a class Model that represents the JSON:

    Public Class RestApiResponseRoot
        Public Property Meta As Meta
        Public Property Resources As List(Of String)
        Public Property Errors As List(Of Object)
    End Class
    Public Class Meta
        <JsonProperty("query_time")>
        Public Property QueryTime As Double
        Public Property Pagination As Pagination
        <JsonProperty("powered_by")>
        Public Property PoweredBy As String
        <JsonProperty("trace_id")>
        Public Property TraceId As Guid
    End Class
    Public Class Pagination
        Public Property Offset As Long
        Public Property Limit As Long
        Public Property Total As Long
    End Class
    

    You can then deserialize the Model's Root object - the class named RestApiResponseRoot here - and access its Properties as usual:

    Dim restApiResponse = JsonConvert.DeserializeObject(Of RestApiResponseRoot)(
        data_response_raw
    )
    ' This is your array of strings
    Dim resources = restApiResponse.Resources
    

    The other JSON response is slightly different, the Response Property contains an array of objects instead of string.
    Some more properties and nested object are added. You just need to adjust the Model.

    Public Class RestApiResponseRoot2
        Public Property Meta As RootObjectMeta
        Public Property Resources As List(Of Resource)
        Public Property Errors As List(Of Object)
    End Class
    
    Public Class RootObjectMeta
        <JsonProperty("query_time")>
        Public Property QueryTime As Double
        <JsonProperty("powered_by")>
        Public Property PoweredBy As String
        <JsonProperty("trace_id")>
        Public Property TraceId As Guid
    End Class
    
    Public Class Resource
        <JsonProperty("device_id")>
        Public Property DeviceId As String
        Public Property Policies As List(Of Policy)
        Public Property Meta As ResourceMeta
    End Class
    
    Public Class ResourceMeta
        Public Property Version As String
    End Class
    
    Public Class Policy
        <JsonProperty("policy_type")>
        Public Property PolicyType As String
        <JsonProperty("policy_id")>
        Public Property PolicyId As String
        Public Property Applied As Boolean
        <JsonProperty("settings_hash")>
        Public Property SettingsHash As String
        <JsonProperty("assigned_date")>
        Public Property AssignedDate As DateTimeOffset
        <JsonProperty("applied_date")>
        Public Property AppliedDate As DateTimeOffset
        <JsonProperty("rule_groups")>
        Public Property RuleGroups As List(Of Object)
    End Class
    

    Dim restApiResponse2 = JsonConvert.DeserializeObject(Of RestApiResponseRoot2)(dr)
    Dim resources As List(Of Resource) = restApiResponse2.Resources
    ' DeviceId of the first Resources object
    Dim deviceId = resources(0).DeviceId
    

    You can use some on-line resources to handle your JSON objects:

    JSON Formatter & Validator

    QuickType - JSON to .Net classes - C#, no VB.Net

    JSON Utils - JSON to .Net classes - includes VB.Net. Somewhat less capable than QuickType.