3

ここで JSON を正しく解析しようとすると問題が発生します。私は次の形式を持ち、JObjects を使用してみましたが、それは 1 つのオブジェクトを別のオブジェクトに分割します。おそらく、例は理にかなっているでしょう:

{
  "completed_in": 0.012,
  "max_id": 136536013832069120,
  "max_id_str": "136536013832069120",
  "next_page": "?page=2&max_id=136536013832069120&q=twitterapi&rpp=1",
  "page": 1,
  "query": "twitterapi",
  "refresh_url": "?since_id=136536013832069120&q=twitterapi",
  "results": [
  {
  "created_at": "Tue, 15 Nov 2011 20:08:17 +0000",
  "from_user": "fakekurrik",
  "from_user_id": 370773112,
  "from_user_id_str": "370773112",
  "from_user_name": "fakekurrik",
  "geo": null,
  "id": 136536013832069120,
  "id_str": "136536013832069120",
  "iso_language_code": "en",
  "metadata": {
    "result_type": "recent"
  },
  "profile_image_url": "http://a1.twimg.com/profile_images/1540298033/phatkicks_normal.jpg",
  "source": "<a href="http://twitter.com/">web</a>",
  "text": "@twitterapi, keep on keeping it real",
  "to_user": "twitterapi",
  "to_user_id": 6253282,
  "to_user_id_str": "6253282",
  "to_user_name": "Twitter API"
  }
],
"results_per_page": 1,
 "since_id": 0,
 "since_id_str": "0"
}

これが私が一つの対象と考えるものです。これらのファイルが何百もあり、タブまたは空白行で区切られているだけです。JObjectを使用すると

   Dim jobj As JObject = JObject.Parse(txtStuff.ToString())

    Dim results As List(Of JToken) = jobj.Children().ToList

結果には、個々のトークンがすべて含まれます。上記のような各オブジェクト (オブジェクト全体) をリストにして処理するにはどうすればよいですか?

4

1 に答える 1

5

ここで 2 つの質問をしているような気がします。

  1. 上記の JSON が与えられた場合、データを適切なオブジェクト構造にするにはどうすればよいでしょうか?
  2. これらのオブジェクトを多数含むファイルがある場合、それらをリストに入れるにはどうすればよいですか?

最初の部分はとても簡単です。JSON に一致するクラス構造を定義しJsonConvert.DeserializeObject()、JSON をそのオブジェクトに逆シリアル化するために使用します。投稿した JSON の場合、クラス構造は次のようになります。

Class RootObject
    Public Property completed_in As Double
    Public Property max_id As Long
    Public Property max_id_str As String
    Public Property next_page As String
    Public Property page As Integer
    Public Property query As String
    Public Property refresh_url As String
    Public Property results As List(Of Result)
    Public Property results_per_page As Integer
    Public Property since_id As Integer
    Public Property since_id_str As String
End Class

Class Result
    Public Property created_at As String
    Public Property from_user As String
    Public Property from_user_id As Integer
    Public Property from_user_id_str As String
    Public Property from_user_name As String
    Public Property geo As Object
    Public Property id As Long
    Public Property id_str As String
    Public Property iso_language_code As String
    Public Property metadata As Metadata
    Public Property profile_image_url As String
    Public Property source As String
    Public Property text As String
    Public Property to_user As String
    Public Property to_user_id As Integer
    Public Property to_user_id_str As String
    Public Property to_user_name As String
End Class

Class Metadata
    Public Property result_type As String
End Class

次のようにデシリアライズできます。

Dim obj As String = JsonConvert.DeserializeObject(Of RootObject)(json)

したがって、この時点でobj、質問で定義したように、1 つのオブジェクトからのすべてのデータが含まれます。これで、これらの JSON オブジェクトの多くがまとめてタブまたは空白行で区切られたファイルがあることがわかりました。この形式は有効な JSON ではないため、ファイル全体を読み取って 1 つの大きな文字列として JSON パーサーに渡すことはできません。(個々のオブジェクトはもちろん有効な JSON ですが、タブや空白行の区切り文字と一緒に並べると、全体が無効になります。)そのため、ファイルを 1 行ずつ (または 1 文字ずつ) 読み取る必要があります。セパレーターを見つけて、パーサーが使用できる有効な JSON オブジェクトに分割します理解する。セパレーターを見つけるたびに、最後のセパレーター以降に読み取ったすべてのデータを取得し、それをデシリアライザーにフィードします。各デシリアライゼーションの結果は有効になり、RootObjectその後、リストに追加できます。

これがどのように機能するかを示すコードを次に示します。必要に応じて微調整する必要があるかもしれませんが、それほど的外れではないと思います。

'' This function will read a file containing a series of JSON objects separated by 
'' some string that is NOT part of the JSON.  Could be a blank line or a tab or 
'' something else.  It will return a list of the deserialized JSON objects.
'' This function relies on two other helper functions (below).
Function ReadJsonFile(fileName As String, separator As String) As List(Of RootObject)
    Dim objects As New List(Of RootObject)
    Using sr As New StreamReader(fileName)
        Dim json As String
        Do
            json = ReadToSeparator(sr, separator)
            If json.Length > 0 Then
                objects.Add(JsonConvert.DeserializeObject(Of RootObject)(json))
            End If
        Loop Until json.Length = 0
    End Using
    Return objects
End Function

'' This function will read and build up a string until the given separator is found.
'' Once the separator is found, it returns the string with the separator removed.
'' If no separator is found before the end of the data is reached, it returns
'' whatever was read to that point.
Function ReadToSeparator(reader As TextReader, separator As String) As String
    Dim sb As New StringBuilder()
    While reader.Peek <> -1
        Dim ch As Char = ChrW(reader.Read())
        sb.Append(ch)
        If TailMatchesSeparator(sb, separator) Then
            sb.Remove(sb.Length - separator.Length, separator.Length)
            Exit While
        End If
    End While
    Return sb.ToString()
End Function

'' This function checks whether the last characters in a StringBuffer match the
'' given separator string.  Returns true if so or false if not.
Function TailMatchesSeparator(sb As StringBuilder, separator As String) As Boolean
    If sb.Length >= separator.Length Then
        Dim i As Integer = sb.Length - 1
        For j As Integer = separator.Length - 1 To 0 Step -1
            If sb(i) <> separator(j) Then
                Return False
            End If
            i = i - 1
        Next
        Return True
    End If
    Return False
End Function

これを使用するにはReadJsonFile、ファイル名と区切り文字列を渡して を呼び出すだけです。例えば:

Dim separator As String = vbCrLf + vbCrLf
Dim objects As List(Of RootObject) = ReadJsonFile("json.txt", separator)
于 2013-10-22T07:40:00.553 に答える