【发布时间】:2019-11-29 16:46:42
【问题描述】:
我在从 JSON 对象中取出嵌套值时遇到问题。 我在谷歌上搜索并想出了一个提供“根”或者说“未嵌套”值的小解决方案。反序列化不会解析嵌套值。现在我被困住了。
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
JSON 文件源:
{
"matchNumber": "222",
"phase": "Bronze Medal Match",
"category": {
"name": "F-67kg",
"gender": "FEMALE",
"subCategory": "OLYMPIC CATEGORY",
"bodyLevel": 22,
"headLevel": 5
},
"blueAthlete": {
"name": "playernameblue",
"wtfId": "wtfidblue",
"flagAbbreviation": "GER"
},
"blueAthleteVideoQuota": 1,
"redAthlete": {
"name": "playernamered",
"wtfId": "wtfidred",
"flagAbbreviation": "AZE"
},
"redAthleteVideoQuota": 1,
"roundsConfig": {
"rounds": 3,
"roundTimeMinutes": 2,
"roundTimeSeconds": 0,
"kyeShiTimeMinutes": 1,
"kyeShiTimeSeconds": 0,
"restTimeMinutes": 1,
"restTimeSeconds": 0,
"goldenPointEnabled": true,
"goldenPointTimeMinutes": 1,
"goldenPointTimeSeconds": 0
},
"differencialScore": 20,
"maxAllowedGamJeoms": 0,
"paraTkdMatch": false
}
由此 JSON 生成的 VB 代码和类:
Public Class Category
Public Property name As String
Public Property gender As String
Public Property subCategory As String
Public Property bodyLevel As String
Public Property headLevel As String
End Class
Public Class BlueAthlete
Public Property name As String
Public Property wtfId As String
Public Property flagAbbreviation As String
End Class
Public Class RedAthlete
Public Property name As String
Public Property wtfId As String
Public Property flagAbbreviation As String
End Class
Public Class RoundsConfig
Public Property rounds As Integer
Public Property roundTimeMinutes As Integer
Public Property roundTimeSeconds As Integer
Public Property kyeShiTimeMinutes As Integer
Public Property kyeShiTimeSeconds As Integer
Public Property restTimeMinutes As Integer
Public Property restTimeSeconds As Integer
Public Property goldenPointEnabled As Boolean
Public Property goldenPointTimeMinutes As Integer
Public Property goldenPointTimeSeconds As Integer
End Class
Public Class RootObject
Public Property matchNumber As String
Public Property phase As String
Public Property category As Category
Public Property blueAthlete As BlueAthlete
Public Property blueAthleteVideoQuota As Integer
Public Property redAthlete As RedAthlete
Public Property redAthleteVideoQuota As Integer
Public Property roundsConfig As RoundsConfig
Public Property differencialScore As Integer
Public Property maxAllowedGamJeoms As Integer
Public Property paraTkdMatch As Boolean
End Class
我尝试解析值的代码:
Dim rootObject As RootObject = JsonConvert.DeserializeObject(Of RootObject)(s)
String.Text = rootObject.matchNumber
String.Text = String.Text & vbCrLf & rootObject.phase
String.Text = String.Text & vbCrLf & rootObject.category.name
String.Text = String.Text & vbCrLf & rootObject.category.gender
String.Text = String.Text & vbCrLf & rootObject.category.subCategory
String.Text = String.Text & vbCrLf & rootObject.category.bodyLevel
String.Text = String.Text & vbCrLf & rootObject.category.headLevel
String.Text = String.Text & vbCrLf & rootObject.blueAthleteVideoQuota
String.Text = String.Text & vbCrLf & rootObject.redAthleteVideoQuota
String.Text = String.Text & vbCrLf & rootObject.differencialScore
String.Text = String.Text & vbCrLf & rootObject.maxAllowedGamJeoms
String.Text = String.Text & vbCrLf & rootObject.paraTkdMatch
代码返回 matchNumber 222,然后发生 System.NullReferenceException。对象未设置为对象的实例
这一行抛出异常: String.Text = String.Text & vbCrLf & rootObject.category.name
一般来说,所有更深的嵌套值都会返回该异常。
所以问题是,如何解决这个问题?
更新: 这是复制的完整代码 - 所以基本上这段代码是一个简单的服务器,通过 POST 请求检索 JSON 数据。 VAR jsonstring(从 s 重命名为 jsonstring)包含接收到的 JSON。 Richtextbox1 还包含仅用于查看收到的 JSON 的 JSON。 Richtextbox2 用于排列值。
Imports System.Threading
Imports System.Net
Imports System.Text
Imports System.IO
Imports System
Imports System.Web
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json.Converters
Imports Newtonsoft.Json.Serialization
Public Class Server
#Region "VARS"
Private listener As HttpListener
Private mainThread As Thread
Dim encoding As New UTF8Encoding
Public Shared JSON_Route As String = ""
Dim jsonstring As String = ""
#End Region
Protected Overrides Sub OnFormClosing(ByVal e As System.Windows.Forms.FormClosingEventArgs)
listener.Abort()
mainThread.Join()
End Sub
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
mainThread = New Thread(AddressOf mainRequestLoop)
mainThread.Start()
End Sub
Private Delegate Sub updateListBoxHandler(ByVal msg As String)
Public Sub UpdateListBox(ByVal msg As String)
If InvokeRequired Then
Invoke(New updateListBoxHandler(AddressOf UpdateListBox), New String() {msg})
Else
ListBox1.Items.Add(msg)
End If
End Sub
Public Class Category
Public Property name As String
Public Property gender As String
Public Property subCategory As String
Public Property bodyLevel As String
Public Property headLevel As String
End Class
Public Class BlueAthlete
Public Property name As String
Public Property wtfId As String
Public Property flagAbbreviation As String
End Class
Public Class RedAthlete
Public Property name As String
Public Property wtfId As String
Public Property flagAbbreviation As String
End Class
Public Class RoundsConfig
Public Property rounds As Integer
Public Property roundTimeMinutes As Integer
Public Property roundTimeSeconds As Integer
Public Property kyeShiTimeMinutes As Integer
Public Property kyeShiTimeSeconds As Integer
Public Property restTimeMinutes As Integer
Public Property restTimeSeconds As Integer
Public Property goldenPointEnabled As Boolean
Public Property goldenPointTimeMinutes As Integer
Public Property goldenPointTimeSeconds As Integer
End Class
Public Class RootObject
Public Property matchNumber As String
Public Property phase As String
Public Property category As Category
Public Property blueAthlete As BlueAthlete
Public Property blueAthleteVideoQuota As Integer
Public Property redAthlete As RedAthlete
Public Property redAthleteVideoQuota As Integer
Public Property roundsConfig As RoundsConfig
Public Property differencialScore As Integer
Public Property maxAllowedGamJeoms As Integer
Public Property paraTkdMatch As Boolean
End Class
Public Sub mainRequestLoop()
listener = New HttpListener()
listener.Prefixes.Add("http://localhost:" & TextBox_Port.Text & "/" & TextBox_Restfulpath.Text & "/")
Try
listener.Start()
Catch ex As Exception
MsgBox("Please start as Admin (with administration rights granted.)")
End Try
Try
Do
Dim ctx As HttpListenerContext = listener.GetContext()
Dim worker As New HttpRequestWorker(ctx, Me)
' ToDo: use threadpool threads probably better
Dim t As New Thread(AddressOf worker.ProcessRequest)
Dim request = ctx.Request
Dim body As Stream = request.InputStream
Dim reader As New StreamReader(body, encoding)
jsonstring = reader.ReadToEnd()
Richtextbox1.Text = jsonstring
Dim rootObject As RootObject = JsonConvert.DeserializeObject(Of RootObject)(s)
RichTextBox2.Text = rootObject.matchNumber
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.phase
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.category.name
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.category.gender
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.category.subCategory
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.category.bodyLevel
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.category.headLevel
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.blueAthleteVideoQuota
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.redAthleteVideoQuota
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.differencialScore
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.maxAllowedGamJeoms
RichTextBox2.Text = RichTextBox2.Text & vbCrLf & rootObject.paraTkdMatch
t.Start()
Loop
Catch ex As Exception
MsgBox(ex.ToString())
End Try
End Sub
' Http Request Handler
Private Class HttpRequestWorker
Private context As HttpListenerContext
Private caller As Server
Public Sub New(ByVal context As HttpListenerContext, ByVal f As Server)
Me.context = context
caller = f
End Sub
' Handle the request
Public Sub ProcessRequest()
Dim msg As String = context.Request.HttpMethod & " " & context.Request.Url.ToString()
JSON_Route = context.Request.Url.ToString()
caller.UpdateListBox(msg)
Dim url As System.Uri = context.Request.Url
Dim path As String = url.GetComponents(UriComponents.Path, UriFormat.SafeUnescaped)
Debug.WriteLine(path)
Dim response As HttpListenerResponse = context.Response
Try
Dim requestError As Boolean
Dim requestError1 As Boolean
requestError = context.Request.HttpMethod.ToUpper() <> "GET" OrElse String.IsNullOrEmpty(path)
requestError1 = context.Request.HttpMethod.ToUpper() <> "POST" OrElse String.IsNullOrEmpty(path)
If Not requestError Then
response.AddHeader("Cache-Control", "no-cache")
response.AddHeader("Pragma", "no-cache")
response.StatusCode = 200
Dim encoding As New UTF8Encoding
response.ContentEncoding = encoding
response.ContentType = "text/html"
Dim responseHtml As String = "Available"
Dim responseHtmlBytes() As Byte = encoding.GetBytes(responseHtml)
response.ContentLength64 = responseHtmlBytes.Length
Dim stream As IO.Stream = response.OutputStream
stream.Write(responseHtmlBytes, 0, responseHtmlBytes.Length)
stream.Close()
Else
response.StatusCode = 404
End If
Catch ex As Exception
response.StatusCode = 500
Finally
response.Close()
End Try
End Sub
End Class
【问题讨论】:
-
我现在可以给你一个正确的答案,但请检查我关于 JSON 主题的一些答案。使用一些可视化工具,然后写出关卡名称,想象一个 json 是一个 x 层的建筑,然后你一层一层地往上走。
-
我找到了你的主题:stackoverflow.com/questions/56970361/… - 我会调查的。看起来很简单。如果可行,我稍后会告诉你。
-
这是其中之一。
-
什么是字符串?您没有将字符串变量命名为 String,对吗?是文本框吗?如果是文本框,不要一遍遍更新UI;这是很多屏幕重绘。在代码中构建一个字符串,最后设置文本框的文本属性一次。
-
我无法重现您的问题。您的代码不会按原样编译,因为未定义
String.Text。如果我将String.Text更改为局部变量Dim Text = rootObject.matchNumber,那么您的代码将成功运行而没有任何错误:dotnetfiddle.net/FEM4h8。你能请edit你的问题分享minimal reproducible example吗?
标签: json vb.net object json.net deserialization