Datenbankabruf via PHP: mehrere Datensätze einlesen

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von SpaceyX.

    Datenbankabruf via PHP: mehrere Datensätze einlesen

    Hi zusammen,

    ich komme nochmal mit der Thematik DB-Abruf über PHP.
    Ich hab ja kein Problem damit, einzelne Datensätze via PHP --> SQL abzurufen.
    Das ist ja alles recht einfach. Aber wie kriege ich es sinnvoll hin, z.B. eine SELECT über eine komplette Tabelle sinnvoll via PHP an VB zu übergeben?
    Oft rufe ich ja ganze Listen ab - irgendwie hab ich da grad eine Blockade :)
    Die Infos die ich im Forum nach vielen Suchen gefunden habe, beziehen sich in erster Linie auf einzelne Datensätze oder klar definierte Felder.

    Ich freu mich auf Hinweise :)
    KlyX
    Chris' Weblog - Mein Blog rund um Vieles :D
    Als Array irgendeiner Art.
    Du möchtest generell ein Datenformat wie JSON oder XML nutzen (ich würde zu JSON raten), welches sich für dich um die korrekte Übermittlung der Daten kümmert.
    Für VB gibts fertige Bibliotheken, die den JSON-Kram wieder auseinandernehmen, PHP kann das nativ (siehe json_encode()).

    JSON hält dir dann auch gleich vielen anderen Ärger an Stellen wie Unicode, Sonderzeichen und Datentypen vom Hals. Sehr praktisch.

    Viele Grüße,
    Manawyrm

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

    Perfekt, dann wird es also JSON sein ;)
    @SpaceyX: danke für den Tipp. Grad via NuGet in mein Projekt geladen.
    Kümmere mich jetzt aber erstmal um die PHP-Seite und dann schau ich mal, wie das genau funktioniert :)
    Komme gerne auf dich zurück :D (könnte gut sein :D)
    Chris' Weblog - Mein Blog rund um Vieles :D
    Hey @SpaceyX
    Hab das soweit hinbekommen, dass ich meine JSON in mein Programm bekomme und auch soweit deserialisiert bekomme.
    Aber: ich brauche die Daten nun erstmal in einem in VB weiterverarbeitenden Format. Meine Idee war es, aus den Daten ein Datatable zu erstellen und diese dann an ein DGV als Quelle zu übergeben.
    (Bisher habe ich immer ohne Datatables und co gearbeitet.. Asche über mein Haupt - kenn mich auch noch nicht wirklich damit aus...)

    Aber wie bekomme ich das hin?

    Sol hole ich mir die Daten ab:

    VB.NET-Quellcode

    1. Using webClient As WebClient = New System.Net.WebClient()
    2. Dim n As WebClient = New WebClient()
    3. 'Die JSON URL wird über das Textfeld json_url geladen
    4. Dim json = n.DownloadString(json_url.Text)
    5. Dim valueOriginal As String = Convert.ToString(json)
    6. Dim table As DataTable = Tabulate(json)
    7. json_dgv.DataSource = table


    Die Tabulate-Funktion habe ich im Web gefunden - der User wollte genau wie ich, die Daten unabhängig vom Inhalt und ohne weitere Definiton eines Layouts einlesen.
    Die Funktion sieht so aus:

    VB.NET-Quellcode

    1. Public Function Tabulate(ByVal json As String) As DataTable
    2. Dim jsonLinq = JObject.Parse(json)
    3. Dim srcArray = jsonLinq.Descendants().Where(Function(d) TypeOf d Is JArray).First()
    4. Dim trgArray = New JArray()
    5. For Each row As JObject In srcArray.Children(Of JObject)()
    6. Dim cleanRow = New JObject()
    7. For Each column As JProperty In row.Properties()
    8. If TypeOf column.Value Is JValue Then
    9. cleanRow.Add(column.Name, column.Value)
    10. End If
    11. Next
    12. trgArray.Add(cleanRow)
    13. Next
    14. Return JsonConvert.DeserializeObject(Of DataTable)(trgArray.ToString())
    15. End Function


    Das Ding läuft beim Starten durch - das DGV bleibt aber komplett leer.

    Ich habe es auch mal so versucht, dass ich die Daten in ein Dataset laden wollte:

    VB.NET-Quellcode

    1. ​Dim data As DataSet = JsonConvert.DeserializeObject(Of DataSet)(json)


    Da bekomme ich aber folgenden Fehler:
    Unexpected JSON token when reading DataTable. Expected StartArray
    , got StartObject


    Irgendwas mach ich falsch :)
    Die API (keine relevanten Daten) liegt aktuell hier und ist aufrufbar: abacado.net/kfzmanager/api.php/fuel
    Chris' Weblog - Mein Blog rund um Vieles :D
    Hi,

    bilde den JSON-String zuerst auf ein Objekt ab. Soll heissen parse Deine Daten in eine Liste von Klassen.

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json
    2. Imports System.IO
    3. Public Class Form1
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. Dim json As String = File.ReadAllText("persons.json")
    6. Dim persons As List(Of Person) = JsonConvert.DeserializeObject(Of List(Of Person))(json)
    7. Me.DataGridView1.DataSource = persons
    8. End Sub
    9. End Class
    10. Public Class Person
    11. <JsonProperty("id")>
    12. Public Property ID As Integer
    13. <JsonProperty("first_name")>
    14. Public Property FirstName As String
    15. <JsonProperty("last_name")>
    16. Public Property Lastname As String
    17. <JsonProperty("email")>
    18. Public Property EMail As String
    19. <JsonProperty("gender")>
    20. Public Property Gender As String
    21. <JsonProperty("ip_address")>
    22. Public Property IpAddress As String
    23. End Class


    So zum Beispiel. Evtl. noch über eine BindingSource an das DGV binden. Hab Dir ein Beispielprojekt angehängt. Ob dies nun der beste Weg ist, kann ich Dir nicht sagen. Ich würde es jedenfalls so machen, da mit das Rumhantieren mit den JObjects zu umständlich ist. So hast Du "bekannte" Objects, mit denen Du arbeiten kannst.
    Dateien
    • WindowsApp12.zip

      (598,67 kB, 108 mal heruntergeladen, zuletzt: )
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Danke dir - klingt soweit machbar.
    Das heisst aber, dass ich somit die Struktur die im JSON enthalten ist immer in Klassen ablegen sollte?
    Sprich: ich muss für jeden Abruf eines JSON mit unterschiedlichem Inhalt entsprechende Klassen anlegen? (Also unterm Strich für jede verwendete Column, richtig?)

    Gibt es einen Weg ohne jegliches parsen in einzelne Klassen? So nach dem Motto: hey, hier ist deine JSON - teil bitte selbst anhand der JSON-Struktur auf und lies alles mal eben ein.
    Oder macht das einfach ganz grundsätzlich keinen Sinn?

    Hab das jetzt mal ausprobiert. Aber ich bekomme mit deiner Methode auch einen Fehler. Hier erstmal der Code - auf mein Projekt angepasst:

    VB.NET-Quellcode

    1. Private Sub get_json_Click(sender As Object, e As EventArgs) Handles get_json.Click
    2. Using webClient As WebClient = New System.Net.WebClient()
    3. Dim n As WebClient = New WebClient()
    4. Dim json = n.DownloadString(json_url.Text)
    5. Dim fuel As List(Of Fuel) = JsonConvert.DeserializeObject(Of List(Of Fuel))(json)
    6. json_dgv.DataSource = fuel
    7. End Using
    8. End Sub


    und die Klasse:

    VB.NET-Quellcode

    1. Public Class Fuel
    2. <JsonProperty("id")>
    3. Public Property ID As Integer
    4. <JsonProperty("fuel_name")>
    5. Public Property Benzin As String
    6. <JsonProperty("fuel_type")>
    7. Public Property Benzin_Typ As String
    8. End Class


    Der Fehler:
    Ein Ausnahmefehler des Typs "Newtonsoft.Json.JsonSerializationException" ist in Newtonsoft.Json.dll aufgetreten.

    Zusätzliche Informationen: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[KFZ_Manager.Fuel]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

    To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

    Stimmt eventuell etwas mit dem JSON-Format nicht?
    Hier ist die exakte Ausgabe des Aufrufs zu finden:
    kfzmanager.abacado.net/api.php/fuel
    Chris' Weblog - Mein Blog rund um Vieles :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „KlyX“ ()

    Da müsste man sich einloggen. Kannst Du bitte einfach einen Beispiel-String hier posten. Am besten den, bei dem Du den Fehler hast.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Hoppla, da hat wohl das Forum beim C&P der URL ein Problem gemacht. Jetzt geht die URL.
    Ansonsten hier die Ausgabe, wie sie rauskommen müsste:

    {
    "fuel": {
    "columns": [
    "id",
    "fuel_name",
    "fuel_type"
    ],
    "records": [
    [
    1,
    "Super E10",
    "Super"
    ],
    [
    2,
    "Super Plus",
    "Super"
    ],
    [
    3,
    "Top Qualität",
    "Super"
    ],
    [
    4,
    "Diesel Standard",
    "Diesel"
    ]
    ]
    }
    }
    Chris' Weblog - Mein Blog rund um Vieles :D
    Nun, da der JSON-String so aussieht, wird wohl meiner Meinung nach das "Mapping" nicht so funktionieren. Eine Darstellung dieser Art habe ich bisher noch nicht gesehen. Mein Vorschlag hier wäre das:

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json.Linq
    2. Imports Newtonsoft.Json
    3. Imports System.IO
    4. Public Class Form1
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. Dim json As String = File.ReadAllText("fuel.json")
    7. Dim tokens As JToken() = JObject.Parse(json).SelectToken("fuel").SelectToken("records").ToArray()
    8. Dim fuels As New List(Of Fuel)
    9. For Each x As JToken In tokens
    10. fuels.Add(New Fuel With {.ID = x(0).Value(Of Integer), .FuelName = x(1).Value(Of String), .FuelType = x(2).Value(Of String)})
    11. Next
    12. Me.DataGridView1.DataSource = fuels
    13. End Sub
    14. End Class
    15. Public Class Fuel
    16. Public Property ID As Integer
    17. Public Property FuelName As String
    18. Public Property FuelType As String
    19. End Class


    Wie gesagt, ich bin auch nicht der Super-Profi, aber sowas in der Art würde ich dann machen.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Okay, so funktioniert es nun. Das macht es aber dann auch komplizierter, was? Immerhin muss ich das JSON in Arrays einlesen, die ich für jede Abfrage mit verschiedenen Ausgaben eigens definieren muss.
    Die ursprüngliche Variante war natürlich einfacher ;)
    Der Output stammt aus dieser API hier: github.com/mevdschee/php-crud-api
    Funktioniert sehr gut und ist einfach zu nutzen. Doof, das der Output wohl nicht ganz standardmässig ist :(
    Chris' Weblog - Mein Blog rund um Vieles :D
    Nene, es ist schon gültiges JSON (soweit ich das beurteilen kann), nur ist die Struktur nicht so gut zu handhaben finde ich. Ausser ich bin total auf dem Holzweg.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o