如何反序列化json [英] How to deserialize json
问题描述
我对使用JSON相当新,我对json的反序列化有问题,我有一个休息服务,它返回一个格式如下的JSON:
{
结果:[
{
meta:[
[
CODICE,
ftString,
16
],
[
DESCRIZIONE,
ftString,
150
],
[
CODCATEGORIA,
ftString,
50
],
[
PREZZO,
ftFloat
],
[
DESCRIZIONEBREVEWEB,
ftString,
100
]
],
数据:[
[
8871_TILAK07,
CALAMITA FERMASOLDI PELLE,
PELLE,
,
CALAMITA FERMASOLDI PELLE
]
]
}
]
}
我尝试了什么:
我试图在.Net中使用Newtonsoft进行反序列化:
< pre lang =vb> Dim articoli 作为列表( of JsonContract.Result)= JsonConvert.DeserializeObject( Of List( of JsonContract.Result) )(ResponseFromServer)
...
公共 类结果
公共 属性数据作为列表( 数据)
结束 类
公开 类数据
' [ [ CODICE, ftString,16],[ DESCRIZIONE, ftString,150],[ COMPOSIZIONE, ftString,100],[ CODCATEGORIA, ftString,50],[ PREZZO ftFloat],[ PREZZOPROMO, ftFloat],[ SCONTOPROMO, ftFloat],[ PROMODADATA, ftTimeStamp],[ PROMOADATA, ftTimeStamp],[ CODMODELLO,ftString,16],[DESCRIZIONEBREVEWEB,ftString,100]]
公共 < span class =code-keyword>属性 Codice 作为 字符串
< span class =code-keyword>公共 属性 Descrizion e 作为 字符串
公共 属性 Composizione 作为 字符串
公开 属性 CodCategoria 作为 字符串
....
结束 类
但是articoli总是一无所获。
如何将json接收到数据集/数据表中
非常感谢提前
这是一个Converter Helper类(转换自C#)用于商业应用。它将转换为/来自POCO< - > JSON。Imports Newtonsoft.Json
Public 类 JsonConverter
公共 共享 功能 FromClass( Of T)(data As T,可选 isEmptyToNull 作为 布尔 = False ,可选 jsonSettings As JsonSerializerSettings = Nothing ) As String
Dim 响应作为 字符串 = ST ring .Empty
If (data IsNot Nothing )然后
尝试 ' try..catch仅在调试期间需要
response = JsonConvert.SerializeObject(data,jsonSettings)
Catch ex As 异常
Debug.WriteLine(ex)
投掷
结束 尝试
结束 如果
返回 如果(isEmptyToNull,( If (response = {}, null,response)),response)
结束 功能
公开 共享 函数 ToClass( Of T)(data As 字符串,可选 jsonSettings 作为 JsonSerializerSettings = Nothing ) As T
Dim response 作为 T = 没什么
如果 不 字符串 .IsNullOrEmpty(data)然后
尝试 ' try..catch仅在调试期间需要
response = If (jsonSettings Nothing ,JsonConvert.DeserializeObject( T)(数据),JsonConvert.DeserializeObject( Of T)(data,jsonSettings))
Catch ex As 异常
Debug.WriteLine(ex)
投掷
结束 尝试
结束 如果
返回回复
结束 功能
结束 类使用它:
Dim raw 作为 新数据()使用
{
.Codice = 字段1,
.Descrizione = 字段2,
.Composizione = 字段3,
.CodCategoria = 字段4
}
Dim json As String = JsonConverter.FromClass(raw)
Dim ra w2 = JsonConverter.ToClass( 数据)(json)
< b>更新
我必须承认,在我查看Richard的解决方案之前,我没有仔细查看JSON数据。
因此,以下更新使用上面的JsonConverter
帮助程序类,但也维护了所需的类结构。您需要做的唯一事情是将自定义ResultDataConverter
属性添加到结果
类。Imports System.IO
Imports Newtonsoft.Json.Linq
< span class =code-keyword> Imports Json = Newtonsoft.Json
Module Module1
Sub Main()
Dim filePath 作为 字符串 = Path.Combine( FilePath, FileName)
Dim data As String = FileHelper.TextRead(filePath)
Dim result = JsonConverter.ToClass( Of 结果)(数据)
Debugger.Break()
结束 Sub
结束 模块
< Json.JsonConverter( GetType (ResultDataConverter))>
公开 类结果
公开 属性数据()作为列表( Of 数据)
结束 类
公开 类数据
公共 属性 CODICE()作为 字符串
公开 属性 DESCRIZIONE()作为 字符串
公共 属性 COMPOSIZIONE() 作为 Strin g
公共 属性 CODCATEGORIA()作为 字符串
公共 属性 PREZZO()作为 单
Public Property PREZZOPROMO() As 单
公共 属性 SCONTOPROMO()作为 单
公开 属性 PROMODADATA()作为 日期
公共 属性 PROMOADATA()作为 日期
公共 属性 CODMODELLO()作为 String
公共 属性 DESCRIZIONEBREVEWEB()作为 字符串
结束 类
公共 类 ResultDataConverter
继承 Json.JsonConverter
公共 覆盖 功能 CanConvert(objectType As 类型) As 布尔
返回 True
结束 功能
公开 覆盖 功能 ReadJson(reader As Json.JsonReader,objectType As 类型,existingValue As 对象,序列化程序作为 Json.JsonSerializer)作为 对象
Dim obj 作为结果= Nothing
如果 reader.TokenType = Json.JsonToken.StartObject 那么
Dim jObject As JObject = JObject.Load(reader)
如果 jObject IsNot Nothing AndAlso jObject.HasValues 然后
Dim result = jObject( result)
如果结果 IsNot 没什么 然后
obj = 新结果()
Dim root = serializer.Deserialize( IList( JObject))(result.CreateReader())
Dim jMeta = root.First()。Children()。Where( Function (x)x .Path = meta)
Dim jData = root.First()。Children()。Where( Function (x)x.Path = data)
Dim lookup = jMeta.Children()_
.Children()_
。选择(功能(x)x.First .ToString())_
。选择(功能(x,i)新 使用 {。x = x,.i = i})_
.ToDictionary( Function (x)xx, Function (x)xi)
Dim dataElements = jData.Children()。Children()。ToList()
obj.Data = 新列表( 数据)()
对于 i 正如 整数 = 0 至 dataElements.Count - 1
Dim element = 新数据()
如果 lookup.Keys.Contains( CODICE)然后
element.CODICE = dataElements(i)(lookup( CODICE))。ToString()
结束 如果
如果 lookup.Keys.Contains( DESCRIZIONE) Then
element.DESCRIZIONE = dataElements(i)(lookup( DESCRIZIONE )。ToString()
结束 如果
' 对所有其他数据属性执行相同操作
obj.Data.Add(element)
下一步
结束 如果
结束 < span class =code-keyword>如果
结束 如果
返回 obj
结束 功能
公共 覆盖 Sub WriteJson(writer As Json.JsonWriter,value As Object ,serializer As Json.JsonSerializer)
投掷 新 NotImplementedException()
结束 Sub
结束 类
公开 类 FileHelper
公开 共享 函数 TextRead(fileName As String ) As String
返回 TextRead(Path.GetFileName( fileName),Path.GetDirectoryName(fileName))
结束 功能
公共 共享 功能 TextRead(fileName 作为 字符串,filePath 作为 〜应变g )作为 字符串
Dim 数据作为 字符串 = 字符串 .Empty
Dim myFile As String = Path.Combine(filePath,fileName)
如果 Directory.Exists(filePath) AndAso File.Exists(myFile)然后
使用 reader = < span class =code-keyword>新 StreamReader(myFile)
data = reader.ReadToEnd()
结束 使用
结束 如果
返回数据
结束 功能
结束 类通过将属性映射封装在自定义转换器中,如果JSON元字段发生变化,将来更容易更新。只需更新Data类属性,然后调整自定义转换器中的映射。
注意:自定义ResultDataConverter
不完整。如果存在不完整的JSON数据,您将需要添加我留下注释的其他属性并防止转换。
您遇到的问题是您尝试的JSON反序列化不代表列表(Of JsonContract.Result)
。它实际上代表一个看起来像这样的对象:
' {结果:[...]}
公开 类 ResultWrapper
公共 属性结果 As 列表( ResultSet)
结束 Class
' {meta:[...],data: [...]}
公开 类 ResultSet
< span class =code-keyword> Public Property meta As List( MetaField)
公众 属性数据作为列表( DataRecord)
结束 类
' [name,...]
公共 类 MetaField:继承列表( 对象)
公开 只读 属性 FieldName 作为 字符串
获取
返回 DirectCast ( 我( 0 ),< span class =code-keyword> String )
结束 获取
结束 属性
结束 类
' [field,...]
公共 类 DataRecord:继承列表( 对象)
< span class =code-keyword>结束 类
...
Dim result As ResultWrapper = JsonConvert.DeserializeObject( of ResultWrapper)(ResponseFromServer)
一旦你得到ResultWrapper
,哟你需要找到第一个ResultSet
,循环遍历meta
列表,找到你想要的属性的索引映射,最后遍历数据
列表并映射每个属性。
Dim resultSet As ResultSet = result.result( 0 )
Dim iCodice 作为 整数 = -1,iDescrizione As Integer = -1,iCodCategoria 作为 整数 = -1,iComposizione 作为 整数 = -1
对于 i As 整数 = 0 resultSet.meta.Count - 1
选择 案例 meta(i).FieldName
案例 CODICE
iCodice = i
案例 DESCRIZIONE
iDescrizione = i
案例 CODCATEGORIA
iCodCategoria = i
< span class =code-keyword> Case COMPOSIZIONE
iComposizione = i
结束 选择
下一步
Dim articoli As 新列表( 数据)(resultSet.data.Count)
对于 每个记录 As DataRecord 在 resultSet.data
Dim item As 新 Data()
如果 iCodice<> -1 然后 item.Codice = DirectCast (记录(iCodice),字符串)
如果 iDescrizione<> -1 然后 item.Descrizione = DirectCast (记录(iDescrizione),字符串)
如果 iCodCategoria<> -1 然后 item.CodCategoria = DirectCast (记录(iCodCategoria),字符串)
如果 iComposizione<> -1 然后 item.Composizione = DirectCast (记录(iComposizione),字符串)
articoli.Add(item)
下一页
Hi, I'm fairly new to using JSON and I have a problem with deserialization of a json, I have a rest service that returns a JSON formatted like this:
{
result: [
{
meta: [
[
"CODICE",
"ftString",
16
],
[
"DESCRIZIONE",
"ftString",
150
],
[
"CODCATEGORIA",
"ftString",
50
],
[
"PREZZO",
"ftFloat"
],
[
"DESCRIZIONEBREVEWEB",
"ftString",
100
]
],
data: [
[
"8871_TILAK07",
"CALAMITA FERMASOLDI IN PELLE",
"PELLE",
"",
"CALAMITA FERMASOLDI IN PELLE"
]
]
}
]
}
What I have tried:
I tried to deserialize with Newtonsoft in .Net :
Dim articoli As List(Of JsonContract.Result) = JsonConvert.DeserializeObject(Of List(Of JsonContract.Result))(ResponseFromServer)
...
Public Class Result
Public Property Data As List(Of Data)
End Class
Public Class Data
'[["CODICE","ftString",16],["DESCRIZIONE","ftString",150],["COMPOSIZIONE","ftString",100],["CODCATEGORIA","ftString",50],["PREZZO","ftFloat"],["PREZZOPROMO","ftFloat"],["SCONTOPROMO","ftFloat"],["PROMODADATA","ftTimeStamp"],["PROMOADATA","ftTimeStamp"],["CODMODELLO","ftString",16],["DESCRIZIONEBREVEWEB","ftString",100]]
Public Property Codice As String
Public Property Descrizione As String
Public Property Composizione As String
Public Property CodCategoria As String
....
End Class
but "articoli" is always nothing.
How can I place the json received in a dataset / datatable
many thanks in advance
Here is a Converter Helper class (converted from C#) used in commercial applications. It will convert to/From POCOs <-> JSON.Imports Newtonsoft.Json Public Class JsonConverter Public Shared Function FromClass(Of T)(data As T, Optional isEmptyToNull As Boolean = False, Optional jsonSettings As JsonSerializerSettings = Nothing) As String Dim response As String = String.Empty If (data IsNot Nothing) Then Try ' try..catch only required during debugging response = JsonConvert.SerializeObject(data, jsonSettings) Catch ex As Exception Debug.WriteLine(ex) Throw End Try End If Return If(isEmptyToNull, (If(response = "{}", "null", response)), response) End Function Public Shared Function ToClass(Of T)(data As String, Optional jsonSettings As JsonSerializerSettings = Nothing) As T Dim response As T = Nothing If Not String.IsNullOrEmpty(data) Then Try ' try..catch only required during debugging response = If(jsonSettings Is Nothing, JsonConvert.DeserializeObject(Of T)(data), JsonConvert.DeserializeObject(Of T)(data, jsonSettings)) Catch ex As Exception Debug.WriteLine(ex) Throw End Try End If Return response End Function End ClassTo Use it:
Dim raw As New Data() With { .Codice = "Field 1", .Descrizione = "Field 2", .Composizione = "Field 3", .CodCategoria = "Field 4" } Dim json As String = JsonConverter.FromClass(raw) Dim raw2 = JsonConverter.ToClass(Of Data)(json)
UPDATE
I must admit, I did not look closely at the JSON data until I looked at Richard's Solution.
So the following update uses the aboveJsonConverter
helper class but also maintains the class structure that you want. The only thing that you need to do is add the customResultDataConverter
attribute to theResult
class.Imports System.IO Imports Newtonsoft.Json.Linq Imports Json = Newtonsoft.Json Module Module1 Sub Main() Dim filePath As String = Path.Combine("FilePath", "FileName") Dim data As String = FileHelper.TextRead(filePath) Dim result = JsonConverter.ToClass(Of Result)(data) Debugger.Break() End Sub End Module <Json.JsonConverter(GetType(ResultDataConverter))> Public Class Result Public Property Data() As List(Of Data) End Class Public Class Data Public Property CODICE() As String Public Property DESCRIZIONE() As String Public Property COMPOSIZIONE() As String Public Property CODCATEGORIA() As String Public Property PREZZO() As Single Public Property PREZZOPROMO() As Single Public Property SCONTOPROMO() As Single Public Property PROMODADATA() As Date Public Property PROMOADATA() As Date Public Property CODMODELLO() As String Public Property DESCRIZIONEBREVEWEB() As String End Class Public Class ResultDataConverter Inherits Json.JsonConverter Public Overrides Function CanConvert(objectType As Type) As Boolean Return True End Function Public Overrides Function ReadJson(reader As Json.JsonReader, objectType As Type, existingValue As Object, serializer As Json.JsonSerializer) As Object Dim obj As Result = Nothing If reader.TokenType = Json.JsonToken.StartObject Then Dim jObject As JObject = JObject.Load(reader) If jObject IsNot Nothing AndAlso jObject.HasValues Then Dim result = jObject("result") If result IsNot Nothing Then obj = New Result() Dim root = serializer.Deserialize(Of IList(Of JObject))(result.CreateReader()) Dim jMeta = root.First().Children().Where(Function(x) x.Path = "meta") Dim jData = root.First().Children().Where(Function(x) x.Path = "data") Dim lookup = jMeta.Children() _ .Children() _ .Select(Function(x) x.First.ToString()) _ .Select(Function(x, i) New With {.x = x, .i = i}) _ .ToDictionary(Function(x) x.x, Function(x) x.i) Dim dataElements = jData.Children().Children().ToList() obj.Data = New List(Of Data)() For i As Integer = 0 To dataElements.Count - 1 Dim element = New Data() If lookup.Keys.Contains("CODICE") Then element.CODICE = dataElements(i)(lookup("CODICE")).ToString() End If If lookup.Keys.Contains("DESCRIZIONE") Then element.DESCRIZIONE = dataElements(i)(lookup("DESCRIZIONE")).ToString() End If ' do the same for all other data properties obj.Data.Add(element) Next End If End If End If Return obj End Function Public Overrides Sub WriteJson(writer As Json.JsonWriter, value As Object, serializer As Json.JsonSerializer) Throw New NotImplementedException() End Sub End Class Public Class FileHelper Public Shared Function TextRead(fileName As String) As String Return TextRead(Path.GetFileName(fileName), Path.GetDirectoryName(fileName)) End Function Public Shared Function TextRead(fileName As String, filePath As String) As String Dim data As String = String.Empty Dim myFile As String = Path.Combine(filePath, fileName) If Directory.Exists(filePath) AndAlso File.Exists(myFile) Then Using reader = New StreamReader(myFile) data = reader.ReadToEnd() End Using End If Return data End Function End ClassBy encapsulating the property mapping in a custom converter, this will make it easier in future to update if the JSON meta fields change. Simply update the Data class properties, then adjust the mappings in the custom converter.
Note: The customResultDataConverter
is incomplete. You will need to add the other properties where I left a comment and bullet-proof the conversion if there is incomplete JSON data.
The problem you have is that the JSON you're trying to deserialize doesn't represent aList(Of JsonContract.Result)
. It actually represents a single object that looks something like this:
' { result: [...] } Public Class ResultWrapper Public Property result As List(Of ResultSet) End Class ' { meta: [...], data: [...] } Public Class ResultSet Public Property meta As List(Of MetaField) Public Property data As List(Of DataRecord) End Class ' ["name", ...] Public Class MetaField : Inherits List(Of Object) Public Readonly Property FieldName As String Get Return DirectCast(Me(0), String) End Get End Property End Class ' [field, ...] Public Class DataRecord : Inherits List(Of Object) End Class ... Dim result As ResultWrapper = JsonConvert.DeserializeObject(Of ResultWrapper)(ResponseFromServer)
Once you've got aResultWrapper
, you'll need to find the firstResultSet
, loop through themeta
list to find the index of the properties you want to map, and finally loop through thedata
list and map each property.
Dim resultSet As ResultSet = result.result(0) Dim iCodice As Integer = -1, iDescrizione As Integer = -1, iCodCategoria As Integer = -1, iComposizione As Integer = -1 For i As Integer = 0 To resultSet.meta.Count - 1 Select Case meta(i).FieldName Case "CODICE" iCodice = i Case "DESCRIZIONE" iDescrizione = i Case "CODCATEGORIA" iCodCategoria = i Case "COMPOSIZIONE" iComposizione = i End Select Next Dim articoli As New List(Of Data)(resultSet.data.Count) For Each record As DataRecord In resultSet.data Dim item As New Data() If iCodice <> -1 Then item.Codice = DirectCast(record(iCodice), String) If iDescrizione <> -1 Then item.Descrizione = DirectCast(record(iDescrizione), String) If iCodCategoria <> -1 Then item.CodCategoria = DirectCast(record(iCodCategoria), String) If iComposizione <> -1 Then item.Composizione = DirectCast(record(iComposizione), String) articoli.Add(item) Next
这篇关于如何反序列化json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!