Как десериализовать большие данные JSON в DataGridView - PullRequest
1 голос
/ 26 мая 2019

Я бы хотел десериализовать большой файл JSON (~ 600 МБ) в DataGridView, не сталкиваясь с ошибкой «maxJsonLength».

Мой код работает нормально для небольших файлов JSON.Но для больших файлов JSON я получаю сообщение об ошибке "maxJsonLength".Есть ли обходной путь или простой способ решить эту проблему, так как я не самый опытный программист?

Private Sub BtnOpenFile_Click(sender As Object, e As EventArgs) Handles BtnOpenFileOld.Click
        OpenFileDialog1.InitialDirectory = "C:\"

        If OpenFileDialog1.ShowDialog = DialogResult.Cancel Then
        End If

        Dim JSonFilePath As String = File.ReadAllText(OpenFileDialog1.FileName)
        LblFilePath.Text = OpenFileDialog1.FileName

        DataGridView1.Rows.Clear()
        DataGridView1.Refresh()

        Dim dict As Object = New JavaScriptSerializer().Deserialize(Of List(Of Object))(JSonFilePath)

        For Each item As Object In dict
            DataGridView1.Rows.Add(item("EMail").ToString, item("Timestamp").ToString, item("Number").ToString)
        Next

    End Sub

Мой файл JSON выглядит как

[
  {
    "EMail": "one@mail.com",
    "Timestamp": "2019-05-25T21:24:06.799381+02:00",
    "Number": 206074,
    "randomtrash1": "notneeded",
    "randomtrash2": "notneeded",
    "randomtrash3": "notneeded",
    "randomtrash4": "notneeded",
    "randomtrash5": "notneeded",
    "randomtrash6": "notneeded",
    "randomtrash7": "notneeded",
    "randomtrash8": "notneeded",
    "randomtrash9": "notneeded"
  },
  {
    "EMail": "two@mail.com",
    "Timestamp": "2019-05-25T21:24:06.8273826+02:00",
    "Number": 7397,
    "randomtrash1": "notneeded",
    "randomtrash2": "notneeded",
    "randomtrash3": "notneeded",
    "randomtrash4": "notneeded",
    "randomtrash5": "notneeded",
    "randomtrash6": "notneeded",
    "randomtrash7": "notneeded",
    "randomtrash8": "notneeded",
    "randomtrash9": "notneeded",
    "randomtrash10": "notneeded",
    "randomtrash11": "notneeded",
    "randomtrash12": "notneeded",
    "randomtrash13": "notneeded",
    "randomtrash14": "notneeded",
    "randomtrash15": "notneeded",
    "randomtrash16": "notneeded",
    "randomtrash17": "notneeded",
    "randomtrash18": "notneeded",
    "randomtrash19": "notneeded",
    "randomtrash20": "notneeded",
    "randomtrash21": "notneeded"
  }
]

Ответы [ 2 ]

0 голосов
/ 26 мая 2019
Imports Newtonsoft.Json

Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Dim str As String = _
            "[" + _
            "  {" + _
            "    ""EMail"": ""one@mail.com""," + _
            "    ""Timestamp"": ""2019-05-25T21:24:06.799381+02:00""," + _
            "    ""Number"": 206074," + _
            "  }," + _
            "  {" + _
            "    ""EMail"": ""two@mail.com""," + _
            "    ""Timestamp"": ""2019-05-25T21:24:06.8273826+02:00""," + _
            "    ""Number"": 7397," + _
            "  }," + _
            "]"

    Try
        Dim list As List(Of jsnn) = JsonConvert.DeserializeObject(Of List(Of jsnn))(str)

        For Each item As jsnn In list
            Console.WriteLine(item.EMail & ": " & item.Timestamp & ": " & item.Number)
        Next

    Catch ex As Exception
        MsgBox(ex.Message)
    End Try

End Sub

End Class

Public Class jsnn
    Public Property EMail As String
    Public Property Timestamp As DateTime
    Public Property Number As Integer
End Class

вот скриншот enter image description here

0 голосов
/ 26 мая 2019

Минимальное исправление, чтобы избежать ошибки maxJsonLength, должно установить JavaScriptSerializer.MaxJsonLength = int.MaxValue, как показано в в этом ответе в Длина строки превышает значение, установленное для свойства maxJsonLength по Таха Рехман Сиддики :

Dim serializer As JavaScriptSerializer = New JavaScriptSerializer()
serializer.MaxJsonLength = Int32.MaxValue
Dim dict As Object = serializer.Deserialize(Of List(Of Object))(JSonFilePath)

Однако в настоящее время вы загружаете файл размером 600 МБ в строку размером 600-1200 МБ, которая приближается к максимальной длине строки .Net . Если размер вашего файла несколько увеличится, вы начнете получать исключения из нехватки памяти. Лучшим подходом будет десериализация непосредственно из файла с использованием потокового решения, однако JavaScriptSerializer не поддерживает потоковую передачу. Таким образом, я бы рекомендовал перейти на , что делает.

Сначала установите Json.NET, как показано здесь . Далее, поскольку вы, кажется, не хотите определять явную модель данных для вашего JSON, создайте следующий статический метод:

Public Module JsonExtensions
    Public Function LoadAnonymousType(Of T)(ByVal path as String, ByVal anonymousTypeObject as T, Optional ByVal settings as JsonSerializerSettings = Nothing) as T
        Using streamReader As TextReader = File.OpenText(path)
            Dim serializer = JsonSerializer.CreateDefault(settings)
            return CType(serializer.Deserialize(streamreader, GetType(T)), T)
        End Using
    End Function
End Module

Для этого необходимо десериализовать содержимое файла, местоположение которого определяется аргументом path, в модель данных типа, указанного в аргументе anonymousTypeObject.

Теперь вы сможете десериализовать свой JSON непосредственно из файла в массив из объектов анонимного типа следующим образом:

Dim array = JsonExtensions.LoadAnonymousType( _
    FileName, _
    { New With {.Email = CType(Nothing, String), .Timestamp = CType(Nothing, String), .Number = CType(Nothing, Long) }} _
)
For Each item In array
    ' DataGridView1.Rows.Add(item("EMail").ToString, item("Timestamp").ToString, item("Number").ToString)
    Console.WriteLine("Email = {0}, Timestamp = {1}, Number = {2}", item.Email, item.Timestamp, item.Number)
Next

В качестве альтернативы вы можете создать явную модель данных следующим образом:

Public Class RootObject
    Public Property Email As String
    Public Property Timestamp As String
    Public Property Number As Long
End Class

И десериализация, как показано в Десериализация JSON из файла :

Dim list As List(Of RootObject) = Nothing
Using streamReader As TextReader = File.OpenText(FileName)
    list = CType(JsonSerializer.CreateDefault().Deserialize(streamReader, GetType(List(Of RootObject))), List(Of RootObject))
End Using
For Each item In list
    ' DataGridView1.Rows.Add(item("EMail").ToString, item("Timestamp").ToString, item("Number").ToString)
    Console.WriteLine("Email = {0}, Timestamp = {1}, Number = {2}", item.Email, item.Timestamp, item.Number)
Next

Демонстрационная скрипка здесь .

...