JSON 中的 .NET 嵌套数组

.NET Nested Arrays In JSON

这是我的 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
    }
  ]
}

我想获取所有图片的链接。我试过:

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

但是,我有这个错误:无法将数组转换为字符串
所以,我尝试了这个:

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

但是,我有同样的错误。我也试过:

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

但是,我有一个新错误:无法将数组转换为字节数组

我应该如何进行?

在您的 JSON 中,sizes 是一个对象数组。不清楚这应该检索什么值:

Dim vimeo_pictures_list As String = vimeo_pictures_api_response_json("data")(0)("sizes")

如果你想做的是得到第一个 link(那里唯一的 string 类型),那么你会写:

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

注意这里的jArraySizes被推断为一个JToken:当然这时候sizes会是什么还不知道,所以Type总是JToken,基地class。我们知道它将是一个 JObjects 的数组,因此这里是 JArray,因为我们可以通过查看 JSON 结构来确定它。

因此,这没有多大意义:

Dim vimeo_pictures_list As Array= vimeo_pictures_api_response_json("data")(0)("sizes")

您可能已经设置了 Option Strict Off,否则将无法编译代码,因为您指定了错误的转换类型(和以前一样)。

因此,例如,要获取数组中的所有 link 个字符串,我们可以这样写:

For Each jSize In jArraySizes
    Console.WriteLine(jSize("link"))
Next

这里,jSize当然还是推断为JToken,同理。我们知道它将是 JObject(出于同样的原因:我们有眼睛)。

如果你想避免总是回到 JSON 结构并在对它做任何事情之前确定你将要处理的类型,你可以预先构建一个 Class 描述 JSON 的模型并反序列化为该模型。
▶ 当您执行此操作时,Intellisense 将启动并显示 Type/Value 每个属性 is/has.

您可以使用在线资源,如 JSON Utils(因为它可以生成 VB.Net 代码),将您的 JSON 转换为 .Net class 结构.
或者,如果 JSON(非常)简单,复制 JSON,然后打开 Visual Studio 和 select
的编辑菜单 Paste Special -> Paste JSON as Classes.

使用 class 模型,我们还可以添加简化 JSON 的反序列化/序列化的方法。在这里,我添加了一个 Public Shared Function Deserialize() 方法。它是静态的(Shared),所以你可以直接调用它:

Dim vimeoPictures = VimeoPicturesHandler.Deserialize([API Response])

请注意,某些属性具有 <JsonProperty()> 描述符属性,因为 JSON 中的某些 属性 名称可能与语言关键字冲突(如 next)。

现在您可以像往常一样将每个对象作为 .Net 属性 值访问。例如:

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

您可以使用 SelectTokens with the JsonPath 递归下降运算符 .. 一次性获取所有链接:

Dim links = JObject.Parse(json).SelectTokens("..link").Select(Function(t) CStr(t)).ToList()

演示 fiddle:https://dotnetfiddle.net/QNJTek