当 json 有多个级别时,将 Json 转换为数据表

Convert Json to Datatable when json has multiple levels

在我的程序中,这是我第一次尝试解析 JSON 内容。
我试图获得的结果是一个包含如下列的数据表:

| Text of group | Text of Item | Command of Item |    

JSON如下:

{
      "Groups": [
        {
          "Items": [
            {
              "Command": "Framework.Windows.Components.ESScrollerForm, ESGrid|SHOW|Χρήστες|ESGOUser|ESGOUser_def|||65535",
              "Key": "834888dd-c4d5-449a-96b7-67db5c3d2692",
              "Text": "Users",
              "ImageIndex": -1
            },
            {
              "Command": "Framework.Windows.Components.ESScrollerForm, ESGrid|SHOW|QuestionaireSurveyorQuery|ESTMTask|QuestionaireSurveyorQuery|||0",
              "Key": "b71de66d-2baf-4452-ada7-8fc67044876b",
              "Text": "QuestionaireSurveyorQuery"
            }
          ],
          "Expanded": true,
          "Tag": "",
          "Key": "b741e67a-a3cd-4b97-91cf-ae9c9d9db7d7",
          "Text": "Settings",
          "ImageIndex": -1
        },
        {
          "Items": [
            {
              "64String": "Soap",
              "Command": "cInvoke|Booked Requests Agent Booking|SHOW|ESMIS|BookedReqAgentBook||False",
              "Key": "bfbc3d4a-ef8a-49a0-918a-331813ba90fb",
              "Text": "Requests Agent Booking",
              "ImageIndex": -1
            },
            {
              "64String": "Jrse",
              "Command": "cInvoke|HHG SF Profit \u0026 Loss|SHOW|ESMIS|HHGFileProfitability||False",
              "Key": "cf1cbffc-aba9-4e0f-8d6c-ba7219932fb6",
              "Text": "HHG SF Profit \u0026\u0026 Loss",
              "ImageIndex": -1
            }
          ],
          "Tag": "..CSShortcuts\HHGReporting.ebl",
          "Key": "eff0d713-a70e-4582-a103-b8cc5cecdad6",
          "Text": "HHGReporting",
          "ImageIndex": -1
       }
    ]
 }

过去,我使用 XPATH 成功解析了复杂的 XML,但现在我使用 Newtonsoft.Json 进行了很多尝试,但没有成功。

我尝试过的是首先使用在线生成器创建 3 类:

Public Class Rootobject
    Public Property Groups() As Group
End Class

Public Class Group
    Public Property Items() As Item
    Public Property Expanded As Boolean
    Public Property Tag As String
    Public Property Key As String
    Public Property Text As String
    Public Property ImageIndex As Integer
End Class

Public Class Item
    Public Property Command As String
    Public Property Key As String
    Public Property Text As String
    Public Property ImageIndex As Integer
    Public Property 64String As String
End Class

是否知道反序列化命令应该如何处理,以便将数据作为具有所描述结构的 DataTable 获取?

您有一个几乎可以工作的 class 模型,需要进行一些更改才能使其按预期工作。

这种语法具有误导性:

Public Property Groups() As Group

这不是对象的集合,它只是类型 Group 的单个对象。
全部改为:

Public Property Groups As Group()
'or 
Public Property Groups As List(Of Group)

要转换为具有特定列选择的 DataTable,您需要迭代 Groups 集合,并针对每个组迭代 Items 集合,以提取您需要的值。
在这里,我使用了一个专门的 class、GroupsHandler,其中包含用于反序列化兼容 JSON 并将结果数据的部分内容转换为 DataTable 的 class 模型结构。

GroupsHandlerclass公开了两个Public方法:

  • Deserialize(),用于转换为.Net classes JSON内容
  • ToDataTable(),用于从反序列化的内容创建数据表。

您可以初始化处理程序并调用这些方法:

Dim handler = New GroupsHandler(Json)
' Only deserialize  
Dim myGroups = handler.Deserialize()

' Deserialize and convert to DataTable
Dim dt = handler.ToDataTable()

Group class 名称在 ItemsGroup 中更改,因为 Group 是语言关键字。
64String 属性 名称在 String64 中更改,因为 属性 名称不能以数字开头。


Imports Newtonsoft.Json

Public Class GroupsHandler
    Private root As GroupsRoot = Nothing
    Private m_json As String = String.Empty

    Public Sub New(json As String)
        m_json = json
    End Sub

    Public Function Deserialize() As List(Of ItemsGroup)
        root = JsonConvert.DeserializeObject(Of GroupsRoot)(m_json)
        Return root.Groups
    End Function

    Public Function ToDataTable() As DataTable
        If root Is Nothing Then
            If String.IsNullOrEmpty(m_json) Then Return Nothing
            Deserialize()
        End If

        Dim dt As New DataTable("Groups")
        dt.Columns.AddRange(New DataColumn() {
            New DataColumn("GroupText", GetType(String)),
            New DataColumn("ItemText", GetType(String)),
            New DataColumn("ItemCommand", GetType(String))
        })

        For Each grp In root.Groups
            For Each item In grp.Items
                dt.Rows.Add(New Object() {grp.Text, item.Text, item.Command})
            Next
        Next
        Return dt
    End Function

    Public Class GroupsRoot
        Public Property Groups As List(Of ItemsGroup)
    End Class

    Public Class ItemsGroup
        Public Property Items As List(Of Item)
        <JsonProperty("Expanded", NullValueHandling:=NullValueHandling.Ignore)>
        Public Property Expanded As Boolean?
        Public Property Tag As String
        Public Property Key As Guid
        Public Property Text As String
        Public Property ImageIndex As Long
    End Class

    Public Class Item
        Public Property Command As String
        Public Property Key As Guid
        Public Property Text As String
        <JsonProperty("ImageIndex", NullValueHandling:=NullValueHandling.Ignore)>
        Public Property ImageIndex As Long?
        <JsonProperty("64String", NullValueHandling:=NullValueHandling.Ignore)>
        Public Property String64 As String
    End Class
End Class