我正在使用JSON.NET对HTTP查询中的JSON响应进行反序列化,但在反序列化方面遇到了问题。
源JSON如下所示:
[
{
"type": "rpc",
"tid": 18,
"action": "TaskSystem",
"method": "createTask",
"result": {
"0": {
"success": true,
"successes": [
[
"Task successfuly created with S/N #22920"
]
]
},
"1": {
"success": true,
"successes": [
[
"Task successfuly created with S/N #22921"
],
"Task #22921 marked as urgent"
]
},
"records": [
{
"id": 22920
},
{
"id": 22921
}
],
"success": true
}
}
]
我一直在使用这些类进行反序列化:
Private Sub Deserialize()
Dim Jobj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Response())(Jstring)
End Sub
Public Class Record
Public Property id As Integer
End Class
Public Class Result
Public Property records As Record()
Public Property success As Boolean
End Class
Public Class Response
Public Property type As String
Public Property tid As Integer
Public Property action As String
Public Property method As String
Public Property result As Result
End Class
但是我正在丢失查询返回的成功/失败消息
我应该如何编写类Result,以便将属性records As Record()、successs As Boolean和以及命名为"0"、"1"等的对象集合起来。。。?
非常感谢你的帮助。
您可以将JSON复制到剪贴板,并使用
编辑->特殊粘贴->将JSON粘贴为类
来大致了解类。所有的机器人都会出错,比如:
' wrong
Public Property successes()() As String
' correct:
Public Property successes As String()()
这似乎奏效了:
Public Class StatusS ' string()() version
Public Property success As Boolean
Public Property successes As List(Of List(Of String))
End Class
Public Class StatusO ' Object() version
Public Property success As Boolean
Public Property successes As List(Of Object)
End Class
机器人也很难处理非法的属性名称,尤其是VB中有很多关键字(End
和Error
很常见)。使用JsonProperty
创建别名(将"0"或"1"映射到合法的东西):
Public Class Result
<JsonProperty("0")>
Public Property StatusA As StatusS
<JsonProperty("1")>
Public Property StatusB As StatusO
Public Property records As List(Of Record)
Public Property success As Boolean
End Class
在他们提供阵列的任何地方,您都可以使用List(Of T)
。
Dim jData = JsonConvert.DeserializeObject(Of Response())(jstr)
Console.WriteLine(jData(0).action)
Console.WriteLine(jData(0).result.records(0).id)
Console.WriteLine(jData(0).result.StatusA.success)
Console.WriteLine(jData(0).result.StatusA.successes(0)(0).ToString)
Console.WriteLine(jData(0).result.StatusB.successes(0).ToString)
结果:
TaskSystem
222920
True
使用序列号#222920"使用序列号22921成功创建任务">
]
很难发现,但[ "Task successfuly ... #22920" ]
后面缺少/多了一个逗号,这可能导致Object
版本与String()()
版本中的一个或另一个可能是打字错误。如果没有,您可以为这两种情况编写一个转换器,或者在StatusO
类中添加一个方法以获得Q+D。这意味着删除括号:
Friend Function GetSuccessMsg(ndx As Int32) As String
If ndx < successes.Count Then
Return successes(ndx).ToString().
Replace("[", "").Replace("]", "").
Replace("""", "").Trim()
End If
Return String.Empty
End Function
Console.WriteLine(jData(0).result.StatusA.GetSuccessMsg(0))
使用序列号22921 成功创建任务
这里有两个不相关的问题:
-
Result
类由一组固定属性和一组变量属性组成,这些属性具有递增的数字名称和值的标准化架构。您希望自动反序列化标准属性,并捕获和反序列化自定义属性。这可以使用
JsonExtensionData
来完成。使用此属性,可以临时将自定义属性反序列化为Dictionary(of String, JToken)
,然后在[OnDeserialized]
回调中转换为Dictionary(Of String, Success)
。这里Success
是一种设计用于捕获JSON的类型,如下所示:{ "success": true, "successes": [ [ "Task successfuly created with S/N #22920" ] ] }
有关文档,请参阅反序列化扩展数据。
-
在上述
Success
类型中,"successes"
数组包含字符串数组和单个字符串。如果您将
successes
属性定义如下:Public Property successes As List(Of List(Of String))
然后,可以使用
SingleOrArrayConverter(Of String)
的变体来处理这一问题,该变体来自如何使用JSON.net处理同一属性的单个项和数组,并通过<JsonProperty(ItemConverterType := GetType(SingleOrArrayConverter(Of String)))>
将其设置为项转换器。
因此,您的最终类将看起来像:
Public Class Success
Public Property success As Boolean
<JsonProperty(ItemConverterType := GetType(SingleOrArrayConverter(Of String)))> _
Public Property successes As List(Of List(Of String))
End Class
Public Class Record
Public Property id As Integer
End Class
Public Class Result
Public Property records As Record()
Public Property success As Boolean
<JsonIgnore> _
Public Property successes as Dictionary(Of string, Success)
<JsonExtensionData> _
Private _additionalData as Dictionary(Of string, JToken)
<System.Runtime.Serialization.OnSerializing> _
Sub OnSerializing(ByVal context as System.Runtime.Serialization.StreamingContext)
If successes IsNot Nothing
_additionalData = successes.ToDictionary(Function(p) p.Key, Function(p) JToken.FromObject(p.Value))
Else
_additionalData = Nothing
End If
End Sub
<System.Runtime.Serialization.OnSerialized> _
Sub OnSerialized(ByVal context as System.Runtime.Serialization.StreamingContext)
_additionalData = Nothing
End Sub
<System.Runtime.Serialization.OnDeserializing> _
Sub OnDeserializing(ByVal context as System.Runtime.Serialization.StreamingContext)
_additionalData = Nothing
End Sub
<System.Runtime.Serialization.OnDeserialized>
Sub OnDeserialized(ByVal context as System.Runtime.Serialization.StreamingContext)
If _additionalData IsNot Nothing
successes = _additionalData.ToDictionary(Function(p) p.Key, Function(p) p.Value.ToObject(Of Success)())
End If
_additionalData = Nothing
End Sub
End Class
Public Class Response
Public Property type As String
Public Property tid As Integer
Public Property action As String
Public Property method As String
Public Property result As Result
End Class
Public Class SingleOrArrayConverter(Of T)
Inherits JsonConverter
Public Overrides ReadOnly Property CanWrite() As Boolean
Get
Return false
End Get
End Property
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim retVal As Object = New List(Of T)()
If reader.TokenType = JsonToken.StartArray Then
serializer.Populate(reader, retVal)
Else
Dim instance As T = DirectCast(serializer.Deserialize(reader, GetType(T)), T)
retVal.Add(instance)
End If
Return retVal
End Function
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(List(Of T))
End Function
End Class
小提琴原型。