我在名为strJSON的变量中有以下JSON字符串。
{
"results":[
{
"templateName":"HUD Section 8",
"userID":"2",
"mobileObjectId":"4582",
"source":"M",
"inspectionType":"A",
"notes":"Window in bedroom needs repair.",
"agencyID":"",
"requestDate":"2014-05-09 00:00:00",
"agencyName":"",
"inspectionTimeBegun":"2014-05-09 14:00:17",
"inspectionDate":"2014-05-09 14:30:00",
"inspectionID":135,
"inspectionTimeComplete":"2014-05-09 14:29:25",
"summaryDecision":"F",
"createdAt":"2014-05-09T18:29:35.050Z",
"updatedAt":"2014-05-09T18:29:35.050Z",
"objectId":"1FgtD6WT8Y",
"ACL":{
"*":{
"read":true
},
"cryZoU5gXJ":{
"write":true,
"read":true
}
}
}
]
}
当我拨打以下代码行时......
ds = Newtonsoft.Json.JsonConvert.DeserializeObject(Of DataSet)(strJSON)
我收到一条消息,说明“指定的参数超出了有效值范围”
使用以下对Parse.com的REST API调用创建JSON字符串。
strJSON = http.QuickGetStr(strURL)
我在其他地方成功使用了这个,虽然Parse类更简单,但是我仔细检查了这个JSON字符串并且看不出任何错误。
关于可能导致此错误的任何想法?
答案 0 :(得分:1)
为了让Json.Net反序列化为DataSet
,JSON必须采用特定格式,如this answer中所述。您的JSON很接近,但问题是ACL
对象。 Json.Net 5.0使用的DataTableConverter
要求表中的所有列都是简单的数据类型,否则会抛出ArgumentOutOfRangeException
(source)。除了简单类型之外,Json.Net 6.0还支持嵌套数据表和数组,但您的ACL数据仍然不符合允许将其正确反序列化为DataSet
的所需格式。你有几个不同的选择来解决这个问题:
更改JSON
如果您控制JSON的格式(即它不是来自第三方),您可以更改它,以便Json.Net 6.0能够将其反序列化为DataSet
。以下是它需要的工作方式:
{
"results": [
{
"templateName": "HUD Section 8",
"userID": "2",
"mobileObjectId": "4582",
"source": "M",
"inspectionType": "A",
"notes": "Window in bedroom needs repair.",
"agencyID": "",
"requestDate": "2014-05-09 00:00:00",
"agencyName": "",
"inspectionTimeBegun": "2014-05-09 14:00:17",
"inspectionDate": "2014-05-09 14:30:00",
"inspectionID": 135,
"inspectionTimeComplete": "2014-05-09 14:29:25",
"summaryDecision": "F",
"createdAt": "2014-05-09T18:29:35.050Z",
"updatedAt": "2014-05-09T18:29:35.050Z",
"objectId": "1FgtD6WT8Y",
"ACL": [
{
"user": "*",
"read": true,
"write": false
},
{
"user": "cryZoU5gXJ",
"read": true,
"write": true
}
]
}
]
}
使用此格式,ACL
表的results
列将包含具有各个ACL行的嵌套DataTable
,每行包含三列user
,{ {1}}和read
。
反序列化为强类型类
您可以反序列化为一组强类型类,而不是反序列化为write
。这种方法的优点是一切都是易于使用的形式。缺点是在创建类之前需要知道JSON中的内容。
您可以使用第三方工具(如json2csharp.com)来帮助从JSON示例中生成类,如另一个答案(现已删除)中所建议的那样,但请注意,这不是万无一失的(并且它不会#39;做VB)。有时您需要手动干预和编辑类。例如,如果在您的问题中从JSON生成类,您会注意到它为每个ACL实例创建了一个固定类。除非您的ACL集合始终只有两个项目,一个名为DataSet
,另一个名为Everyone
,否则这将无效。我认为ACL的集合更有可能是可变的,因此对这些使用CryZoU5gXJ
是有意义的。以下是我建议的课程:
Dictionary
有了这个类结构,你可以像这样反序列化:
Class RootObject
Public Property results As List(Of Result)
End Class
Class Result
Public Property templateName As String
Public Property userID As String
Public Property mobileObjectId As String
Public Property source As String
Public Property inspectionType As String
Public Property notes As String
Public Property agencyID As String
Public Property requestDate As String
Public Property agencyName As String
Public Property inspectionTimeBegun As String
Public Property inspectionDate As String
Public Property inspectionID As Integer
Public Property inspectionTimeComplete As String
Public Property summaryDecision As String
Public Property createdAt As String
Public Property updatedAt As String
Public Property objectId As String
Public Property ACL As Dictionary(Of String, ACL)
End Class
Class ACL
Public Property read As Boolean
Public Property write As Boolean
End Class
对于ACL,每个字典条目的键将是用户ID(或示例中的Dim root As RootObject = JsonConvert.DeserializeObject(Of RootObject)(strJSON)
)。如果您实际上并不关心ACL,则可以省略*
类中的ACL
属性。默认情况下,Json.Net将跳过JSON中存在但在类中不存在的属性。
使用LINQ-to-JSON API解析JSON
使用Json.Net,总有不止一种方法可以给猫皮肤涂抹。当您正在解析的JSON变化很大和/或您不想创建用于接收数据的类时,Json.Net的LINQ-to-JSON API会非常闪耀。您可以将任何有效的JSON反序列化为JToken
对象的层次结构,然后根据需要将它们分开。例如,如果您只需要从每个结果中选择一些信息,则可以执行以下操作:
Result
您可以使用相同的方法从JSON手动构建Dim token As JToken = JToken.Parse(json)
For Each result As JObject In token("results").Children(Of JObject)()
Console.WriteLine("userID: " + result("userID").ToString())
Console.WriteLine("templateName: " + result("templateName").ToString())
Console.WriteLine("inspectionID: " + result("inspectionID").ToString())
Console.WriteLine("inspectionType: " + result("inspectionType").ToString())
Console.WriteLine("inspectionDate: " + result("inspectionDate").ToString())
Console.WriteLine("summaryDecision: " + result("summaryDecision").ToString())
Console.WriteLine("notes: " + result("notes").ToString())
Next
。这是一个通用函数,它将JSON反序列化为DataSet
但忽略任何复杂对象(例如ACL)而不是抛出异常:
DataSet
当然,如果您需要ACL,则需要自定义此方法以将该数据转换为代码可以使用的表单。我会把那部分留给你。
答案 1 :(得分:0)
如果符合某个标准,Json.Net将仅直接解析为DataSet。请参阅this answer了解所需的布局。
但是,您可以反序列化为XML文档,并使用DataSet对象的ReadXml方法为您加载它。有关如何执行此操作的详细信息,请参阅this question。
(对于数据集结构详细信息,HT到Brian Rogers)