C# 将动态JSON数据高效反序列化到datatable中
我们正在开发一个程序,从一组没有一致模式设置的服务器中获取幻灯片图像数据(我担心这是无效的,但我还不够熟练,无法调用)。作为独立的、不相关的研究人员,我们对服务器没有影响 数据是通过大量表格(n>50)手动输入的(大部分情况下),字段不一致(数据可追溯到90年代)。以下是一个响应示例:C# 将动态JSON数据高效反序列化到datatable中,c#,json,vb.net,serialization,json.net,C#,Json,Vb.net,Serialization,Json.net,我们正在开发一个程序,从一组没有一致模式设置的服务器中获取幻灯片图像数据(我担心这是无效的,但我还不够熟练,无法调用)。作为独立的、不相关的研究人员,我们对服务器没有影响 数据是通过大量表格(n>50)手动输入的(大部分情况下),字段不一致(数据可追溯到90年代)。以下是一个响应示例: { "form12873": [ { "id": "9202075838", "timestamp": "2015-06-25 10:24:51", "u
{
"form12873": [
{
"id": "9202075838",
"timestamp": "2015-06-25 10:24:51",
"user_agent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit\/600.6.3 (KHTML, like Gecko) Version\/8.0.6 Safari\/600.6.3",
"remote_addr": "[Re.dact.ed]",
"processed": "1",
"data": {
"33885124": {
"field": "33885124",
"value": "CDat Lab",
"flat_value": "CDat Lab",
"label": "Completed by:",
"type": "select"
},
''**Several more fields as above**''...
"33884660": {
"field": "33884660",
"value": {
"slideX": "2456123",
"slideY": "456632",
"label": "K-20150322148",
"approved": "1",
"score": "30144"
},
"flat_value": "slideX = 2456123\nslideY = 456632\nlabel = K-20150322148\napproved = 1\nscore = 30144",
"label": "Slide Stats:",
"type": "slidestats"
},
''**Some of the fields are as above...
"31970564": {
"field": "31970564",
"value": [
"System",
"Crated",
"Mirax",
"NanoZoomer",
"ThinPrep",
"Aperio",
"Intellisite"
],
"flat_value": "System\nCrated\nMirax\nNanoZoomer\nThinPrep\nAperio\nIntellisite",
"label": "System Information",
"type": "checkbox"
},
''**Some of the values are Arrays...
"33883781": {
"field": "33883781",
"selection": "Retain",
"label": "4. Retain\/Remove\/Review",
"type": "selectdrop"
},
''**Some of the fields don't have the same children
"52792890": {
"field": "52792890",
"image": "'A really large byte[], removed for ease of reading'",
"type": "image"
}
''**Somewhere near the end of each response is the actual image...
}
},
{
"id": "33884681",
''**Then it continues on as above until the end:
}
], "total": 170, "pages": 5, "pretty_id": "478125624983" }
在过去,当我能够做到这一点时,我已经知道如何处理它(创建一个定义了字段、值等的数据类)
尝试以下解决方案:
var result = JsonConvert.DeserializeObject<List<Dictionary<string,
Dictionary<string, string>>>>(content);
我的最终目标也是要得到一个数据表,循环/图像字节让我担心试图回归到下一个孩子。然后,我尝试使用第一个数组进行反序列化,结果是nill
如果有一个快速的方法来处理这个问题,我很喜欢这个解决方案。如果问题是我试图处理垃圾JSON,我希望参考一下当前标准被打破的地方(这样我至少可以尝试让其他机构改变他们的服务器)。也就是说,不管怎样,我可能不得不处理它,即使它是循环
*注意:该项目是在VB.net中启动的,所以我们一直保持这种方式,但无论如何我可能会决定移植到C。用这两种语言编写代码都很好
下面是一个未标记的Json示例,应该可以用于测试。我的最终目标是将其扁平化为一个数据表:
{
"form12873": [
{
"id": "9202075838",
"timestamp": "2015-06-25 10:24:51",
"user_agent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit\/600.6.3 (KHTML, like Gecko) Version\/8.0.6 Safari\/600.6.3",
"remote_addr": "[Re.dact.ed]",
"processed": "1",
"data": {
"33885124": {
"field": "33885124",
"value": "CDat Lab",
"flat_value": "CDat Lab",
"label": "Completed by:",
"type": "select"
},
"33884660": {
"field": "33884660",
"value": {
"slideX": "2456123",
"slideY": "456632",
"label": "K-20150322148",
"approved": "1",
"score": "30144"
},
"flat_value": "slideX = 2456123\nslideY = 456632\nlabel = K-20150322148\napproved = 1\nscore = 30144",
"label": "Slide Stats:",
"type": "slidestats"
},
"31970564": {
"field": "31970564",
"value": [
"System",
"Crated",
"Mirax",
"NanoZoomer",
"ThinPrep",
"Aperio",
"Intellisite"
],
"flat_value": "System\nCrated\nMirax\nNanoZoomer\nThinPrep\nAperio\nIntellisite",
"label": "System Information",
"type": "checkbox"
},
"33883781": {
"field": "33883781",
"selection": "Retain",
"label": "4. Retain\/Remove\/Review",
"type": "select"
}
}
}
], "total": 170, "pages": 5, "pretty_id": "478125624983" }
可以将
数据列
添加到数据表
,即使它已经包含数据行
我不怎么使用JSON,但我使用狡猾的XML的一般方法是将其分解为一个键值对流,其中键是XPATH“地址”,值是节点(不包括子节点)的内容,然后在流中循环以构建
数据表
。也许可以在JSONPath中采用类似的方法。可以将数据列
添加到数据表
,即使它已经包含数据行
我不怎么使用JSON,但我使用狡猾的XML的一般方法是将其分解为一个键值对流,其中键是XPATH“地址”,值是节点(不包括子节点)的内容,然后在流中循环以构建
数据表
。也许JSONPath也可以采用类似的方法。下面这个丑陋的装置可以(大致)做你想做的事情。将json源字符串作为参数提供给反序列化ToDataTable
,并收集结果datatable。它对你的样品有效。我不能保证它会在你的其他数据中起作用。这里的目的是提供一个工作启动工具包,您可以学习、理解、调试和调整它以满足您的需要
私有函数反序列化ToDataTable(ByVal jsource作为字符串)
Dim JRootObject=JObject.Parse(jsource)
Dim Children=JRootObject.SelectTokens($…data.*).ToArray
Dim记录=子项。属于(JObject的)类型。ToArray
将列表作为新列表(字典(字符串、对象))
对于记录中的每个rec
添加(反序列化字典(rec))
下一个
Dim fieldnames=dicList.SelectMany(功能(d)d.Keys).Distinct.ToArray
Dim dt作为新数据表
对于fieldname中的每个fieldname
添加(字段名,GetType(对象))
下一个
将行变暗为数据行
对于dicList中的每个dic
行=dt.NewRow
对于dic中的每个kvp
行设置字段(kvp.Key,kvp.Value)
下一个
dt.行.添加(行)
下一个
返回dt
端函数
私有函数反序列化字典(ByVal json_对象作为JObject)作为字典(字符串,对象)
Dim dic=新字典(字符串、对象)
对于json_object.Properties中的每个字段
选择Case field.Value.Type
Case JTokenType.Array
Dim子对象=新作业对象
尺寸项目=0
对于field.Value中的每个标记
子对象(“项目”&项目)=标记
项目+=1
下一个
Dim subdic=反序列化字典(子对象)
对于细分卡中的每个kvp
dic(kvp.键)=kvp.值
下一个
Case JTokenType.Boolean
dic(field.Name)=field.Value.ToObject(布尔型)
案例JTokenType.Bytes
dic(field.Name)=field.Value.ToObject(字节()的)
案例JTokenType.日期
dic(field.Name)=field.Value.ToObject(日期)
Case JTokenType.Float
dic(field.Name)=field.Value.ToObject(双精度)
案例JTokenType.Guid
dic(field.Name)=field.Value.ToObject(Guid的)
案例JTokenType.Integer
dic(field.Name)=field.Value.ToObject(整数的)
Case JTokenType.Object
Dim subdic=反序列化字典(field.Value)
对于细分卡中的每个kvp
dic(kvp.键)=kvp.值
下一个
Case JTokenType.String
尝试
dic(field.Name)=field.Value.ToObject(字符串的)
特例
dic(field.Name)=field.Value.ToObject(对象的)
结束尝试
案例JTokenType.TimeSpan
dic(field.Name)=field.Value.ToObject(时间跨度的)
其他情况
dic(field.Name)=field.Value.ToString
结束选择
下一个
返回dic
端函数
使用上述代码时必须注意这一点:
{
"A":"aaaa",
"B":"bbbb",
"C":{
"D":"dddd",
"E":"eeee",
"F":"ffff"
}
}
}
将成为
A |B |D |E |F
----+----+----+----+----
aaaa|bbbb|dddd|eeee|ffff
A |B |D |E |F
----+----+----+----+----
aaaa|bbbb|d2d2|e2e2|f2f2
{
"A":"aaaa",
"B":"bbbb",
"C":{
"D":"d1d1",
"E":"e1e1",
"F":"f1f1"
},
"G":{
"D":"d2d2",
"E":"e2e2",
"F":"f2f2"
}
}
}
将成为
A |B |D |E |F
----+----+----+----+----
aaaa|bbbb|dddd|eeee|ffff
A |B |D |E |F
----+----+----+----+----
aaaa|bbbb|d2d2|e2e2|f2f2
<