私のアプリケーションは、JSONデータを返すHTTPリクエストを多く扱っています。私はそれを処理するためにJSON.NETライブラリを使用します。JSON.NETオブジェクトのデータバインディング:実装方法
これらのデータはWinformsのデータバインディングコントロール(ほとんどComboBox
およびDataGridView
)に表示する必要があります。現時点ではデータの編集は意図されておらず、ユーザーフレンドリーな方法でデータを表示する必要があります。
私はDataTable
へIEnumerable(Of JToken)
を変換即興変換ルーチンを書いた:
Module JsonAsDataTable
<Runtime.CompilerServices.Extension> Public Function ToDataTable(ByVal jtokens As IEnumerable(Of JToken), Optional ByVal trim_object_columns As Boolean = False, Optional ByVal castToCLRtypes As Boolean = False, Optional ByVal orderBy As String = Nothing) As DataTable
Dim dt As New DataTable, sdt As DataTable, dr, sdr As DataRow, dateproperty As Date
If jtokens IsNot Nothing Then
For Each jt In jtokens
dr = dt.NewRow
For Each jp In jt.Children(Of JProperty)
sdt = Nothing
If Not dt.Columns.Contains(jp.Name) Then dt.Columns.Add(jp.Name, IIf(castToCLRtypes, GetType(Object), GetType(JToken)))
If jp.Value.Type = JTokenType.Object AndAlso jp.Value.Children.Count = 1 AndAlso jp.Value.First.Type = JTokenType.Property AndAlso DirectCast(jp.Value.First, JProperty).Name = "date" Then
If Date.TryParse(DirectCast(jp.Value.First, JProperty).Value, dateproperty) Then
dr.SetField(jp.Name, New JValue(dateproperty))
Else
dr.SetField(jp.Name, JValue.CreateNull)
End If
Else
dr.SetField(jp.Name, jp.Value)
If jp.Value.Type = JTokenType.Object Then
sdt = AsDataTable({jp.Value}, trim_object_columns)
ElseIf jp.Value.Type = JTokenType.Array Then
sdt = AsDataTable(jp.Value, trim_object_columns)
End If
If sdt IsNot Nothing Then
sdr = sdt.Select.FirstOrDefault
For Each sdc As DataColumn In sdt.Columns
If Not dt.Columns.Contains(jp.Name & "." & sdc.ColumnName) Then dt.Columns.Add(jp.Name & "." & sdc.ColumnName, GetType(Object))
If sdr IsNot Nothing Then dr.SetField(jp.Name & "." & sdc.ColumnName, sdr(sdc.ColumnName))
Next
If trim_object_columns Then dt.Columns.Remove(jp.Name)
End If
End If
Next
dt.Rows.Add(dr)
Next
If castToCLRtypes Then
For Each drow In dt.Select
For Each dcol As DataColumn In dt.Columns
If TypeOf drow(dcol) Is JToken Then drow(dcol) = ToField(drow(dcol))
Next
Next
End If
If dt.Rows.Count > 0 AndAlso Not String.IsNullOrEmpty(orderBy) Then
dt = dt.Select("", orderBy).CopyToDataTable
End If
End If
Return dt
End Function
<Runtime.CompilerServices.Extension> Friend Function ToField(token As JToken) As Object
If token Is Nothing Then Return Nothing
Select Case token.Type
Case JTokenType.Boolean
Return token.Value(Of Boolean)
Case JTokenType.Bytes
Return token.Value(Of Byte())
Case JTokenType.Date
Return token.Value(Of Date)
Case JTokenType.Float
Return token.Value(Of Double)
Case JTokenType.Guid
Return token.Value(Of Guid)
Case JTokenType.Integer
Return token.Value(Of Integer)
Case JTokenType.Null
Return Nothing
Case JTokenType.Property
Return ExtractObjectFrom(CType(token, JProperty).Value)
Case JTokenType.String
Return token.Value(Of String)
Case JTokenType.TimeSpan
Return token.Value(Of TimeSpan)
Case JTokenType.Uri
Return token.Value(Of Uri)
Case Else
Return token.ToString
End Select
End Function
End Module
今、私は私の解決策は、クリーンでも信頼性もない意識です。 DataGridView
に表示されるものを取得するために私が考えたのは、JTokenのシンプルなArrayが許さない列ヘッダーをクリックすることでデータをソートできる方法です。
したがって、これらのJTokenオブジェクトをラップするカスタムクラス、およびおそらくDataGridView
がソートのような機能を有効にして処理する方法でそれらをリストするCollectionクラスを記述したいと思います(これは私には不可欠です)とフィルタリング(これは達成のための特別賞です)。
質問:最小限のインターフェイスのセットこれらのクラスは、これを実現するために実装する必要がありますか?