如何反序列化json [英] How to deserialize json

查看:76
本文介绍了如何反序列化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 Class

To 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 above JsonConverter helper class but also maintains the class structure that you want. The only thing that you need to do is add the custom ResultDataConverter attribute to the Result 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 Class

By 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 custom ResultDataConverter 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 a List(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 a ResultWrapper, you'll need to find the first ResultSet, loop through the meta list to find the index of the properties you want to map, and finally loop through the data 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆