Reputation: 453
Here's my json:
{
"total": 1,
"page": 1,
"per_page": 25,
"paging": {
"next": null,
"previous": null,
"first": "/users/4061973/pictures?access_token=&page=1",
"last": "/users/4061973/pictures?access_token=&page=1"
},
"data": [
{
"uri": "/users/4061973/pictures/32598345",
"active": true,
"type": "custom",
"sizes": [
{
"width": 30,
"height": 30,
"link": "https://i.vimeocdn.com/portrait/32598345_30x30"
},
{
"width": 72,
"height": 72,
"link": "https://i.vimeocdn.com/portrait/32598345_72x72"
},
{
"width": 75,
"height": 75,
"link": "https://i.vimeocdn.com/portrait/32598345_75x75"
},
{
"width": 100,
"height": 100,
"link": "https://i.vimeocdn.com/portrait/32598345_100x100"
},
{
"width": 144,
"height": 144,
"link": "https://i.vimeocdn.com/portrait/32598345_144x144"
},
{
"width": 216,
"height": 216,
"link": "https://i.vimeocdn.com/portrait/32598345_216x216"
},
{
"width": 288,
"height": 288,
"link": "https://i.vimeocdn.com/portrait/32598345_288x288"
},
{
"width": 300,
"height": 300,
"link": "https://i.vimeocdn.com/portrait/32598345_300x300"
},
{
"width": 360,
"height": 360,
"link": "https://i.vimeocdn.com/portrait/32598345_360x360"
}
],
"resource_key": "",
"default_picture": false
}
]
}
I want to get the links of all images. I have tried:
vimeo_pictures_api_response_json = Newtonsoft.Json.Linq.JObject.Parse(vimeo_pictures_response_request_txt.ToString())
Dim vimeo_pictures_list As String = vimeo_pictures_api_response_json("data")(0)("sizes")
But, I have this error: Can not convert array to string
So, I tried this:
vimeo_pictures_api_response_json = Newtonsoft.Json.Linq.JObject.Parse(vimeo_pictures_response_request_txt.ToString())
Dim vimeo_pictures_list As String = vimeo_pictures_api_response_json("data")(0)("sizes")
But, I have the same error. I also tried:
vimeo_pictures_api_response_json = Newtonsoft.Json.Linq.JObject.Parse(vimeo_pictures_response_request_txt.ToString())
Dim vimeo_pictures_list As Array= vimeo_pictures_api_response_json("data")(0)("sizes")
But, I have a new error: Can not convert array to byte array
How should I proceed?
Upvotes: 1
Views: 272
Reputation: 129707
You could use SelectTokens
with the JsonPath recursive descent operator ..
to get all the links in one go:
Dim links = JObject.Parse(json).SelectTokens("..link").Select(Function(t) CStr(t)).ToList()
Demo fiddle: https://dotnetfiddle.net/QNJTek
Upvotes: 0
Reputation: 32248
In your JSON, sizes
is an array of objects. It's no clear what value this was supposed to retrieve:
Dim vimeo_pictures_list As String = vimeo_pictures_api_response_json("data")(0)("sizes")
If what you want to do is to get the first link
(the only string
Type there), then you'd write:
Dim vimeoObjects = JObject.Parse([API Response])
Dim jArraySizes = vimeoObjects("data").First()("sizes")
Dim firstLink = vimeoObjects("data").First()("sizes").First()("link")
' Or
Dim firstLink = vimeoObjects("data")(0)("sizes")(0)("link")
Note that jArraySizes
, here, is inferred as a JToken
: of course, at this time, what sizes
will be is unknown, so the Type is always JToken
, the base class. We know it will be an array of JObjects
, thus a JArray
here, because we can determine this by looking at the JSON structure.
Hence, this doesn't make much sense:
Dim vimeo_pictures_list As Array= vimeo_pictures_api_response_json("data")(0)("sizes")
You probably have set Option Strict Off
, otherwise it would be impossible to compile the code, since you're specifying the wrong conversion Type (as before).
Hence, to get, e.g., all link
strings in the array, we can write:
For Each jSize In jArraySizes
Console.WriteLine(jSize("link"))
Next
Here, jSize
is of course still inferred as a JToken
, for the same reason. We know it will be a JObject
(for the same reason: we have eyes).
If you want to avoid to always go back to the JSON structure and determine what kind of Type you'll be dealing with before doing anything with it, you can pre-build a Class Model that describes the JSON and deserialize to this model instead.
▶ When you do this, Intellisense will then kick in and it will show you what Type/Value each of the Properties is/has.
You can use on-line resources, as JSON Utils (since it can generate VB.Net code), to convert your JSON to a .Net class structure.
Or, if the JSON is (very) simple, copy the JSON, then open the Edit menu of Visual Studio and select
Paste Special -> Paste JSON as Classes
.
Using a class Model, we can also add methods that simplify the deserialization / serialization of the JSON. Here, I've added A Public Shared Function Deserialize()
method. It's static (Shared
), so you can call it directly:
Dim vimeoPictures = VimeoPicturesHandler.Deserialize([API Response])
Note that some Properties have a <JsonProperty()>
descriptor Attribute, since some Property names in the JSON may conflict with language keywords (as next
).
Now you can access each object as a .Net Property value as usual. E.g.,:
Console.WriteLine(vimeoPictures.Paging.FirstPage)
Console.WriteLine(vimeoPictures.Paging.LastPage)
For Each sizeObj In vimeoPictures.Data.First().Sizes
Console.WriteLine(sizeObj.Link)
Console.WriteLine(sizeObj.Width)
Console.WriteLine(sizeObj.Height)
Next
Imports Newtonsoft.Json
Public Class VimeoPicturesHandler
Public Shared Function Deserialize(json As String) As VimeoPicturesRoot
Return JsonConvert.DeserializeObject(Of VimeoPicturesRoot)(json)
End Function
Public Class VimeoPicturesRoot
Public Property Total As Integer
Public Property Page As Integer
<JsonProperty("per_page")>
Public Property PerPage As Integer
Public Property Paging As Paging
Public Property Data As DataElement()
End Class
Public Class Paging
<JsonProperty("next")>
Public Property NextPage As String
<JsonProperty("previous")>
Public Property PreviousPage As String
<JsonProperty("first")>
Public Property FirstPage As String
<JsonProperty("last")>
Public Property LastPage As String
End Class
Public Class DataElement
<JsonProperty("uri")>
Public Property Url As String
Public Property Active As Boolean
<JsonProperty("type")>
Public Property DataType As String
Public Property Sizes As Size()
Public Property ResourceKey As String
<JsonProperty("default_picture")>
Public Property DefaultPicture As Boolean
End Class
Public Class Size
Public Property Width As Integer
Public Property Height As Integer
Public Property Link As String
End Class
End Class
Upvotes: 2