I am having trouble trying to get JSON parsed correctly here. I have the following format and tried using JObjects, but what it does is split one object into its different objects. Perhaps an example will make sense:
我在尝试正确解析JSON时遇到问题。我有以下格式并尝试使用JObject,但它的作用是将一个对象拆分为不同的对象。也许一个例子是有道理的:
{
"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"
}
This is what I consider one object. I have files that have hundreds of these and just separated by a tab or blank line. Now if I use JObject
这是我认为的一个对象。我有几百个这样的文件,只是用制表符或空行分隔。现在,如果我使用JObject
Dim jobj As JObject = JObject.Parse(txtStuff.ToString())
Dim results As List(Of JToken) = jobj.Children().ToList
Results contains all the individual tokens. How can I get each object like the above (the entire object) into a list to process?
结果包含所有单个令牌。如何将上面的每个对象(整个对象)放入要处理的列表中?
1 个解决方案
#1
5
It sounds like you're really asking two questions here.
听起来你真的在这里问了两个问题。
- Given the above JSON, how do I get the data into a nice object structure?
- 鉴于上述JSON,我如何将数据转换为一个漂亮的对象结构?
- Given that I have files containing lots of these objects, how do I get them into a list?
- 鉴于我有包含大量这些对象的文件,我如何将它们放入列表中?
The first part is very easy. Just define a class structure that matches your JSON, then use JsonConvert.DeserializeObject()
to deserialize the JSON into that object. For the JSON you posted, the class structure would look something like this:
第一部分非常简单。只需定义一个与您的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
You can deserialize it like this:
您可以像这样反序列化它:
Dim obj As String = JsonConvert.DeserializeObject(Of RootObject)(json)
So at this point, obj
will contain all the data from one object as you have defined it in your question. Now, you have indicated that you have a file that has many of these JSON objects together separated by a tab or a blank line. You can't just read the whole file in and give it to the JSON parser as one big string because this format isn't valid JSON. (Each individual object is valid JSON of course, but when strung together with tabs or blank line separators, the whole is not valid.) So, you will need to read the file in, line by line (or perhaps character by character) to find the separators and break it up into valid JSON objects that the parser can understand. Each time you find a separator, take all the data that you've read since the last separator and feed that to the deserializer. The result of each deserialization will be a valid RootObject
which you can then add to a list as you go along.
所以在这一点上,obj将包含你在问题中定义的一个对象的所有数据。现在,您已经指出您有一个文件,其中包含许多这些JSON对象,它们由制表符或空行分隔开来。您不能只读取整个文件并将其作为一个大字符串提供给JSON解析器,因为此格式不是有效的JSON。 (当然,每个单独的对象都是有效的JSON,但是当与制表符或空行分隔符串在一起时,整体无效。)因此,您需要逐行读取文件(或者可能逐个字符地读取)找到分隔符并将其分解为解析器可以理解的有效JSON对象。每次找到分隔符时,请获取自上次分隔符以来读取的所有数据,并将其提供给反序列化程序。每个反序列化的结果都是一个有效的RootObject,然后您可以随时添加到列表中。
Here is some code to give you an idea of how this might work. You may have to tweak it, depending on your needs, but I'm guessing it's not that far off the mark.
这里有一些代码可以让您了解这可能如何工作。根据您的需要,您可能需要调整它,但我猜它并不是那么遥远。
'' 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
To use this, just call ReadJsonFile
, passing a file name and a separator string. For example:
要使用它,只需调用ReadJsonFile,传递文件名和分隔符字符串。例如:
Dim separator As String = vbCrLf + vbCrLf
Dim objects As List(Of RootObject) = ReadJsonFile("json.txt", separator)
#1
5
It sounds like you're really asking two questions here.
听起来你真的在这里问了两个问题。
- Given the above JSON, how do I get the data into a nice object structure?
- 鉴于上述JSON,我如何将数据转换为一个漂亮的对象结构?
- Given that I have files containing lots of these objects, how do I get them into a list?
- 鉴于我有包含大量这些对象的文件,我如何将它们放入列表中?
The first part is very easy. Just define a class structure that matches your JSON, then use JsonConvert.DeserializeObject()
to deserialize the JSON into that object. For the JSON you posted, the class structure would look something like this:
第一部分非常简单。只需定义一个与您的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
You can deserialize it like this:
您可以像这样反序列化它:
Dim obj As String = JsonConvert.DeserializeObject(Of RootObject)(json)
So at this point, obj
will contain all the data from one object as you have defined it in your question. Now, you have indicated that you have a file that has many of these JSON objects together separated by a tab or a blank line. You can't just read the whole file in and give it to the JSON parser as one big string because this format isn't valid JSON. (Each individual object is valid JSON of course, but when strung together with tabs or blank line separators, the whole is not valid.) So, you will need to read the file in, line by line (or perhaps character by character) to find the separators and break it up into valid JSON objects that the parser can understand. Each time you find a separator, take all the data that you've read since the last separator and feed that to the deserializer. The result of each deserialization will be a valid RootObject
which you can then add to a list as you go along.
所以在这一点上,obj将包含你在问题中定义的一个对象的所有数据。现在,您已经指出您有一个文件,其中包含许多这些JSON对象,它们由制表符或空行分隔开来。您不能只读取整个文件并将其作为一个大字符串提供给JSON解析器,因为此格式不是有效的JSON。 (当然,每个单独的对象都是有效的JSON,但是当与制表符或空行分隔符串在一起时,整体无效。)因此,您需要逐行读取文件(或者可能逐个字符地读取)找到分隔符并将其分解为解析器可以理解的有效JSON对象。每次找到分隔符时,请获取自上次分隔符以来读取的所有数据,并将其提供给反序列化程序。每个反序列化的结果都是一个有效的RootObject,然后您可以随时添加到列表中。
Here is some code to give you an idea of how this might work. You may have to tweak it, depending on your needs, but I'm guessing it's not that far off the mark.
这里有一些代码可以让您了解这可能如何工作。根据您的需要,您可能需要调整它,但我猜它并不是那么遥远。
'' 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
To use this, just call ReadJsonFile
, passing a file name and a separator string. For example:
要使用它,只需调用ReadJsonFile,传递文件名和分隔符字符串。例如:
Dim separator As String = vbCrLf + vbCrLf
Dim objects As List(Of RootObject) = ReadJsonFile("json.txt", separator)