我刚开始使用JSON.net,在使用一些json时遇到了麻烦,这些json有时以数组的形式出现,有时以单个对象的形式出现。下面是我在json中看到的一个示例。
其中一种方式是……
{
"Make": "Dodge",
"Model": "Charger",
"Lines": [
{
"line": "base",
"engine": "v6",
"color": "red"
},
{
"line": "R/T",
"engine": "v8",
"color": "black"
}
],
"Year": "2013"
}它可以通过另一种方式进入
{
"Make": "Dodge",
"Model": "Charger",
"Lines": {
"line": "base",
"engine": "v6",
"color": "red"
},
"Year": "2013"
}下面是我在代码中使用的代码,它在第一种情况下工作,在第二种情况下抛出异常。我一直在网上寻找实现这一点的方法,我真的卡住了。
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class
Public Class jsonCarLines
Public Property line As String
Public Property engine As String
Public Property color As String
End Class
Module Module1
Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
Sub Main()
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
Console.WriteLine("Make: " & car.make)
Console.WriteLine("Model: " & car.model)
Console.WriteLine("Year: " & car.year)
Console.WriteLine("Lines: ")
For Each ln As jsonCarLines In car.lines
Console.WriteLine(" Name: " & ln.line)
Console.WriteLine(" Engine: " & ln.engine)
Console.WriteLine(" Color: " & ln.color)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module我猜这可能需要一个自定义的JsonConverter,但是我不知道如何设置它。
发布于 2015-02-09 07:02:16
下面是如何让链接的duplicate question中的SingleOrArrayConverter解决方案适用于您的用例。
首先,这里是VB翻译的转换器代码。将其保存到项目中某个位置的类文件中。然后,您可以轻松地将其重用于任何未来类似的案例。
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class SingleOrArrayConverter(Of T)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(List(Of T))
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim token As JToken = JToken.Load(reader)
If (token.Type = JTokenType.Array) Then
Return token.ToObject(Of List(Of T))()
End If
Return New List(Of T) From {token.ToObject(Of T)()}
End Function
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
End Class现在您有了这个转换器,任何时候您的属性既可以是列表,也可以是单个项,您所要做的就是在类中将其声明为列表,然后使用JsonConverter属性注释该列表,以便它使用SingleOrArrayConverter类。在您的示例中,它将如下所示:
Public Class jsonCar
Public Property make As String
Public Property model As String
<JsonConverter(GetType(SingleOrArrayConverter(Of jsonCarLines)))>
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class然后,只需像往常一样反序列化,它就会按预期工作。
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)下面是一个完整的演示:https://dotnetfiddle.net/msYNeQ
发布于 2015-02-08 23:44:31
您可以通过如下方式修改jsonCar类来实现这一点
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property linesCollection As List(Of jsonCarLines) // Change name
Public Property lines As String // Change the type to string
Public Property year As String
End Class代码应如下所示:
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
If (car.lines.StartsWith("[")) Then
car.linesCollection = JsonConvert.DeserializeObject(List(Of jsonCarLines))(car.lines)
Else
car.linesCollection = new List(Of jsonCarLines)
car.linesCollection.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(car.lines))
EndIf发布于 2015-02-09 04:54:43
感谢crowcoder和Kundan。我将这两种方法结合起来,想出了一种可以同时使用两种json输入的方法。这是最终的代码。
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property linesArray As List(Of jsonCarLines)
Public Property year As String
End Class
Public Class jsonCarLines
Public Property line As String
Public Property engine As String
Public Property color As String
End Class
Module Module1
'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
Sub Main()
Dim obj As JObject = JsonConvert.DeserializeObject(json)
Dim ln As JToken = obj("Lines")
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JArray)) Then
car.linesArray = JsonConvert.DeserializeObject(Of List(Of jsonCarLines))(JsonConvert.SerializeObject(ln))
End If
If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JObject)) Then
car.linesArray = New List(Of jsonCarLines)
car.linesArray.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(JsonConvert.SerializeObject(ln)))
End If
Console.WriteLine("Make: " & car.make)
Console.WriteLine("Model: " & car.model)
Console.WriteLine("Year: " & car.year)
Console.WriteLine("Lines: ")
For Each line As jsonCarLines In car.linesArray
Console.WriteLine(" Name: " & line.line)
Console.WriteLine(" Engine: " & line.engine)
Console.WriteLine(" Color: " & line.color)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module非常感谢你的快速回复。这解决了我花了很多时间断断续续地试图弄清楚的事情。
https://stackoverflow.com/questions/28395700
复制相似问题