JSON Elemente auslesen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    JSON Elemente auslesen

    Hallo Leute,

    normalerweise lese ich JSON Dateien mit dem Dictonary aus. Aber leider habe ich aktuell eine sehr "verzwickte" JSON, wo ich mit dem Dictionary nicht weit springe.

    Die Datei enthält jeweils Blöcke mit Color, length, rects, start und text.
    Wobei mich hier jeweils nur die Werte "color" und die rects interessieren.
    Solange in jedem Color-Elementnur ein Rects Element enthalten ist, geht das einwandfrei mit dem Dictionary auszulesen.
    Beim ersten Element, sind jedoch 3 rects-Werte unter einem color Element gelistet.

    Ich bräuchte aus den Infos folgende Werte:

    color | x | y | width | height

    Wie würdet Ihr das Problem lösen?


    Hier die JSON:

    VB.NET-Quellcode

    1. {
    2. "highlights": [
    3. [
    4. {
    5. "color": 5,
    6. "length": 1002,
    7. "rects": [
    8. {
    9. "height": 40.019002375296736,
    10. "width": 1070.8830608449466,
    11. "x": 155.00461475073303,
    12. "y": 781.7047980301736
    13. },
    14. {
    15. "height": 40.01900237529708,
    16. "width": 1063.1356314253637,
    17. "x": 153.9380445321778,
    18. "y": 816.9214441294905
    19. },
    20. {
    21. "height": 40.01900237529691,
    22. "width": 994.080794599447,
    23. "x": 153.93583943781545,
    24. "y": 852.138158077865
    25. }
    26. ],
    27. "start": 690,
    28. "text": "###"
    29. },
    30. {
    31. "color": 5,
    32. "length": 305,
    33. "rects": [
    34. {
    35. "height": 40.01895148850406,
    36. "width": 1156.5250924080965,
    37. "x": 74.9678567265671,
    38. "y": 1272.6045418419915
    39. }
    40. ],
    41. "start": 1695,
    42. "text": "####"
    43. },
    44. {
    45. "color": 5,
    46. "length": 30,
    47. "rects": [
    48. {
    49. "height": 40.019002375296736,
    50. "width": 335.1346853079534,
    51. "x": 74.43469035313987,
    52. "y": 387.1176815803147
    53. }
    54. ],
    55. "start": 162,
    56. "text": "###"
    57. }
    58. ]
    59. ]
    60. }
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Ich würde das Objekt nachbauen und mit Newtonsoft deserialisieren.

    newtonsoft.com/json
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Ich würde Klassen erstellen, die die Struktur widerspiegeln.

    PS: Wie sieht denn dein Code aus? Ich vermute die übersiehst das rects ein Array ist.
    Lass dir die Klassen generieren und nimm wie schon erwähnt Newtonsoft.json.
    Hier kannste dir die Klassen in C# generieren lassen. Zwar nicht VB, aber auch dafür gibts Converter.
    app.quicktype.io/?l=csharp
    Spoiler anzeigen

    C#-Quellcode

    1. // <auto-generated />
    2. //
    3. // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    4. //
    5. // using dive26;
    6. //
    7. // var highlights = Highlights.FromJson(jsonString);
    8. namespace dive26
    9. {
    10. using System;
    11. using System.Collections.Generic;
    12. using System.Globalization;
    13. using Newtonsoft.Json;
    14. using Newtonsoft.Json.Converters;
    15. public partial class Highlights
    16. {
    17. [JsonProperty("highlights")]
    18. public List<List<Highlight>> HighlightsHighlights { get; set; }
    19. }
    20. public partial class Highlight
    21. {
    22. [JsonProperty("color")]
    23. public long Color { get; set; }
    24. [JsonProperty("length")]
    25. public long Length { get; set; }
    26. [JsonProperty("rects")]
    27. public List<Rect> Rects { get; set; }
    28. [JsonProperty("start")]
    29. public long Start { get; set; }
    30. [JsonProperty("text")]
    31. public string Text { get; set; }
    32. }
    33. public partial class Rect
    34. {
    35. [JsonProperty("height")]
    36. public double Height { get; set; }
    37. [JsonProperty("width")]
    38. public double Width { get; set; }
    39. [JsonProperty("x")]
    40. public double X { get; set; }
    41. [JsonProperty("y")]
    42. public double Y { get; set; }
    43. }
    44. public partial class Highlights
    45. {
    46. public static Highlights FromJson(string json) => JsonConvert.DeserializeObject<Highlights>(json, dive26.Converter.Settings);
    47. }
    48. public static class Serialize
    49. {
    50. public static string ToJson(this Highlights self) => JsonConvert.SerializeObject(self, dive26.Converter.Settings);
    51. }
    52. internal static class Converter
    53. {
    54. public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    55. {
    56. MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
    57. DateParseHandling = DateParseHandling.None,
    58. Converters =
    59. {
    60. new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
    61. },
    62. };
    63. }
    64. }


    Ich würde das Objekt nachbauen und mit Newtonsoft deserialisieren.

    Das wäre auch irgendwie meine Idee.
    Ich arbeite (gerne) mit Structure - da kenne ich mich aus. Könnte ich das mit Newtonsoft irgendwie in eine passende Structure einlesen?
    Leider habe ich keinen Tau wie ich das angehen soll ;)

    Lass dir die Klassen generieren und nimm wie schon erwähnt Newtonsoft.json.

    Mit Klassen habe ich so gut wie keine Erfahrungen, aber zur Not arbeite ich mich auch da ein.

    Wie sieht denn dein Code aus?

    Bis jetzt leider nur eine Mischung aus String-Operationen und Dictionary. Das möchte ich ändern.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Mit Klassen habe ich so gut wie keine Erfahrungen, aber zur Not arbeite ich mich auch da ein.


    Solltest du nicht nur zur Not machen, arbeiten mit Klassen gehört zu Grundlagen, ohne Klassen ist kein Object-Orientiertes-Programmieren möglich, was zu unwartbaren ellenlangen Spaghetti Code führt. In der Kürze liegt die Würze, das geht nur mit OOP.

    Edit: @dive26
    5 Minuten arbeit, inkl. anlegen des Projektes. Alle Rects auslesen. Wobei man die KlassenNamen noch verbessern könnte, wie auch den PropertyNamen HighlightsHighlights .

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json
    2. Imports System.Runtime.CompilerServices
    3. Public Class Form1
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. Dim json As String = "{ ""highlights"": [ [ { ""color"": 5, ""length"": 1002, ""rects"": [ { ""height"": 40.019002375296736, ""width"": 1070.8830608449466, ""x"": 155.00461475073303, ""y"": 781.7047980301736 }, { ""height"": 40.01900237529708, ""width"": 1063.1356314253637, ""x"": 153.9380445321778, ""y"": 816.9214441294905 }, { ""height"": 40.01900237529691, ""width"": 994.080794599447, ""x"": 153.93583943781545, ""y"": 852.138158077865 } ], ""start"": 690, ""text"": ""###"" }, { ""color"": 5, ""length"": 305, ""rects"": [ { ""height"": 40.01895148850406, ""width"": 1156.5250924080965, ""x"": 74.9678567265671, ""y"": 1272.6045418419915 } ], ""start"": 1695, ""text"": ""####"" }, { ""color"": 5, ""length"": 30, ""rects"": [ { ""height"": 40.019002375296736, ""width"": 335.1346853079534, ""x"": 74.43469035313987, ""y"": 387.1176815803147 } ], ""start"": 162, ""text"": ""###"" } ] ]}"
    6. Dim j As Highlights = Highlights.FromJson(json)
    7. For Each itm As List(Of Highlight) In j.HighlightsHighlights
    8. For Each itm2 As Highlight In itm
    9. For Each r As Rect In itm2.Rects
    10. Debug.WriteLine($"X:{r.X} Y:{r.Y} Width:{r.Width} Height:{r.Height}")
    11. Next
    12. Next
    13. Next
    14. End Sub
    15. End Class
    16. ' <auto-generated />
    17. '
    18. ' To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    19. '
    20. ' using dive26;
    21. '
    22. ' var highlights = Highlights.FromJson(jsonString);
    23. Namespace dive26
    24. Partial Public Class Highlights
    25. <JsonProperty("highlights")>
    26. Public Property HighlightsHighlights As List(Of List(Of Highlight))
    27. End Class
    28. Partial Public Class Highlight
    29. <JsonProperty("color")>
    30. Public Property Color As Long
    31. <JsonProperty("length")>
    32. Public Property Length As Long
    33. <JsonProperty("rects")>
    34. Public Property Rects As List(Of Rect)
    35. <JsonProperty("start")>
    36. Public Property Start As Long
    37. <JsonProperty("text")>
    38. Public Property Text As String
    39. End Class
    40. Partial Public Class Rect
    41. <JsonProperty("height")>
    42. Public Property Height As Double
    43. <JsonProperty("width")>
    44. Public Property Width As Double
    45. <JsonProperty("x")>
    46. Public Property X As Double
    47. <JsonProperty("y")>
    48. Public Property Y As Double
    49. End Class
    50. Partial Public Class Highlights
    51. Public Shared Function FromJson(ByVal json As String) As Highlights
    52. Return JsonConvert.DeserializeObject(Of Highlights)(json, Settings)
    53. End Function
    54. End Class
    55. Public Module Serialize
    56. <Extension()>
    57. Public Function ToJson(ByVal self As Highlights) As String
    58. Return JsonConvert.SerializeObject(self, Settings)
    59. End Function
    60. End Module
    61. Friend Module Converter
    62. Public ReadOnly Settings As JsonSerializerSettings = New JsonSerializerSettings With {
    63. .MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
    64. .DateParseHandling = DateParseHandling.None
    65. }
    66. End Module
    67. End Namespace

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „Takafusa“ ()

    @Takafusa
    Du bist ein Schatz.

    Solltest du nicht nur zur Not machen, arbeiten mit Klassen gehört zu Grundlagen, ohne Klassen ist kein Object-Orientiertes-Programmieren möglich, was zu unwartbaren ellenlangen Spaghetti Code führt

    Da hast Du natürlich vollkommen Recht. Aber mit Deinem Code ist schon einmal der Anfang dazu gemacht. Ich hatte in der Tat schon angefangen eine Klasse zu schreiben, wusste aber nicht so genau wie ich die rects in eine "Unterliste" packen sollte. As List(Of Rect) wärs gewesen. Wär ich nie drauf gekommen. Vielen vielen herzlichen Dank.

    Hier mein ganzer Code. Wobei ich die Daten dann wieder in die bereits existierende Structure gefüllt habe, da alles andere ja schon fertig ausprogrammiert war.

    VB.NET-Quellcode

    1. Structure HighLighters_struct
    2. Dim Farbe As Integer
    3. Dim x As Double
    4. Dim y As Double
    5. Dim breite As Double
    6. Dim hoehe As Double
    7. Dim textlaenge As Integer
    8. Dim textinhalt As String
    9. Dim start As Integer
    10. End Structure
    11. Public HighLighters(2000) As HighLighters_struct


    VB.NET-Quellcode

    1. Option Strict On
    2. Imports Newtonsoft.Json
    3. Imports System.Runtime.CompilerServices
    4. Imports RMHLJSONParser
    5. Module Newton
    6. Public Sub LeseHighLighterJSON(JSONDatei As String)
    7. ReDim HighLighters(2000)
    8. Dim LetztesElementMitFarbInfo As Integer = 0
    9. Dim Zaehler As Integer = 0
    10. Dim JSONString As String = My.Computer.FileSystem.ReadAllText(JSONDatei)
    11. Dim j As Highlights = Highlights.FromJson(JSONString)
    12. For Each itm As List(Of Highlight) In j.HighlighterElemente
    13. For Each itm2 As Highlight In itm
    14. 'Schleife für jede Markierung (enthält Color)
    15. HighLighters(Zaehler).Farbe = CInt(itm2.Color)
    16. HighLighters(Zaehler).textlaenge = CInt(itm2.Length)
    17. HighLighters(Zaehler).textinhalt = itm2.Text.ToString
    18. HighLighters(Zaehler).start = CInt(itm2.Start)
    19. LetztesElementMitFarbInfo = Zaehler
    20. For Each r As Rect In itm2.Rects
    21. 'Schleife für jedes rect
    22. HighLighters(Zaehler).x = CDbl(r.X)
    23. HighLighters(Zaehler).y = CDbl(r.Y)
    24. HighLighters(Zaehler).breite = CDbl(r.Width)
    25. HighLighters(Zaehler).hoehe = CDbl(r.Height)
    26. If HighLighters(Zaehler).Farbe = 0 Then
    27. 'Erbt die Eigenschaften des letzten Highlighters, falls nicht vorhanden
    28. HighLighters(Zaehler).Farbe = HighLighters(LetztesElementMitFarbInfo).Farbe
    29. HighLighters(Zaehler).textlaenge = HighLighters(LetztesElementMitFarbInfo).textlaenge
    30. HighLighters(Zaehler).textinhalt = HighLighters(LetztesElementMitFarbInfo).textinhalt
    31. HighLighters(Zaehler).start = HighLighters(LetztesElementMitFarbInfo).start
    32. End If
    33. Zaehler += 1
    34. Next
    35. Next
    36. Next
    37. End Sub
    38. End Module
    39. Namespace Global.RMHLJSONParser
    40. Partial Public Class Highlights
    41. <JsonProperty("highlights")>
    42. Public Property HighlighterElemente As List(Of List(Of Highlight))
    43. End Class
    44. Partial Public Class Highlight
    45. <JsonProperty("color")>
    46. Public Property Color As Long
    47. <JsonProperty("length")>
    48. Public Property Length As Long
    49. <JsonProperty("rects")>
    50. Public Property Rects As List(Of Rect)
    51. <JsonProperty("start")>
    52. Public Property Start As Long
    53. <JsonProperty("text")>
    54. Public Property Text As String
    55. End Class
    56. Partial Public Class Rect
    57. <JsonProperty("height")>
    58. Public Property Height As Double
    59. <JsonProperty("width")>
    60. Public Property Width As Double
    61. <JsonProperty("x")>
    62. Public Property X As Double
    63. <JsonProperty("y")>
    64. Public Property Y As Double
    65. End Class
    66. Partial Public Class Highlights
    67. Public Shared Function FromJson(ByVal json As String) As Highlights
    68. Return JsonConvert.DeserializeObject(Of Highlights)(json, Settings)
    69. End Function
    70. End Class
    71. Public Module Serialize
    72. <Extension()>
    73. Public Function ToJson(ByVal self As Highlights) As String
    74. Return JsonConvert.SerializeObject(self, Settings)
    75. End Function
    76. End Module
    77. Friend Module Converter
    78. Public ReadOnly Settings As New JsonSerializerSettings With {
    79. .MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
    80. .DateParseHandling = DateParseHandling.None
    81. }
    82. End Module
    83. End Namespace
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    As List(Of Rect) wärs gewesen


    Man hätte auch mit nem Array was machen können. Aber ich weiss ja du hattest es damit auch nicht so(List of T), daher ganz fies beim Json->Class-Generator List(of T) anstatt Array gewählt(kann man einstellen). War scheinbar eine gute Idee, scheinst dich damit anzufreunden, kann dir irgendwann vorteilhaft sein.
    hier eine Variante mit RegEx

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. Dim json As String = "{ ""highlights"": [ [ { ""color"": 5, ""length"": 1002, ""rects"": [ { ""height"": 40.019002375296736, ""width"": 1070.8830608449466, ""x"": 155.00461475073303, ""y"": 781.7047980301736 }, { ""height"": 40.01900237529708, ""width"": 1063.1356314253637, ""x"": 153.9380445321778, ""y"": 816.9214441294905 }, { ""height"": 40.01900237529691, ""width"": 994.080794599447, ""x"": 153.93583943781545, ""y"": 852.138158077865 } ], ""start"": 690, ""text"": ""###"" }, { ""color"": 5, ""length"": 305, ""rects"": [ { ""height"": 40.01895148850406, ""width"": 1156.5250924080965, ""x"": 74.9678567265671, ""y"": 1272.6045418419915 } ], ""start"": 1695, ""text"": ""####"" }, { ""color"": 5, ""length"": 30, ""rects"": [ { ""height"": 40.019002375296736, ""width"": 335.1346853079534, ""x"": 74.43469035313987, ""y"": 387.1176815803147 } ], ""start"": 162, ""text"": ""###"" } ] ]}"
    4. 'Dim json As String = IO.File.ReadAllText("dein Pfad zur Datei")
    5. Dim r As New Regex("(?:\""|\')([^""]*)(?:\""|\')(?=:)(?:\:\s*)(?:\"")?(true|false|[-0-9]+[\.]*[\d]*(?=,)|[0-9a-zA-Z\(\)\@\:\,\/\!\+\-\.\$\ \\\']*)(?:\"")?")
    6. Dim matches As MatchCollection = r.Matches(json)
    7. For Each m As Match In matches
    8. 'alles:
    9. 'Debug.WriteLine(m.Groups(1).Value & ":" & m.Groups(2).Value)
    10. 'filtern:
    11. If m.Groups(1).Value.StartsWith("length") Then
    12. Debug.WriteLine(m.Groups(1).Value & ":" & m.Groups(2).Value)
    13. End If
    14. Next
    15. End Sub



    an alle, Guten Rutsch ins neue Jahr
    Hihi, mit der Kanone auf Spatzen schießen und das Rad dabei neu erfinden, ich erfinde zwar auch gern Räder neu, aber IMO ist Newtonsoft.Json die bessere Variante als Regex, denn das ist genau für diesen Zweck entwickelt worden und ist sogar OpenSource. Zudem ist es doch schöner mit dafür erstellten Klassen und De-/Seriallisierung zu arbeiten anstatt mit Regex-Gruppen, auch empfinde ich das als vielfach übersichtlicher.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Takafusa“ ()

    Takafusa schrieb:

    ' To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
    '
    ' using dive26;
    '
    ' var highlights = Highlights.FromJson(jsonString);

    Wie bzw. wo wird dieses Kommando abgesetzt?
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „INOPIAE“ ()

    Das wird uns Takafusa nicht mehr beantworten, da der User uns vor einiger Zeit verlassen hat.

    *closed
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.