JSONDecoder funktioniert nicht

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • JSONDecoder funktioniert nicht

    Hallo Zusammen,
    das Problem ist recht schnell erklärt. Ich habe folgendes geschrieben um mein Json Data zu ein struct zu konvertieren.

    Quellcode

    1. let jsonstruct:HealthMainStruct = try JSONDecoder().decode(HealthMainStruct.self, from: data!) as! HealthMainStruct
    Leider werden einige Felder mit den Werten anderer Felder beschrieben und andere mit vollkommen unrealistischen Daten.
    Mit dem JSONDecoder() bekomme ich folgende JSON Daten. Das Feld "int3v3" hat nun den Wert von Climate/temperature bekommen.

    IST:

    Quellcode

    1. ->>>{
    2. health = {
    3. alarm = {
    4. humidityMax = 0;
    5. temperatureMax = 0;
    6. temperatureMin = 0;
    7. voltage3v3extmax = 1;
    8. voltage3v3extmin = 0;
    9. voltage3v3intmax = 1;
    10. voltage3v3intmin = 0;
    11. voltagebattmax = 1;
    12. voltagebattmin = 0;
    13. };
    14. climate = {
    15. humidity = 14;
    16. temperature = -71625361283;
    17. };
    18. voltages = {
    19. batt = 58428;
    20. ext3v3 = 9430;
    21. int3v3 = 36;
    22. };
    23. };
    24. successful = 1;
    25. }
    Alles anzeigen


    Ich habe das gleiche noch mit dem "alten" JSONSerialization versucht und hiermit funktioniert alles wunderbar!

    Quellcode

    1. let test = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)
    2. print(test)

    So sollte eigentlich mein JSON aussehen:

    Quellcode

    1. {
    2. health = {
    3. alarm = {
    4. humidityMax = 0;
    5. temperatureMax = 0;
    6. temperatureMin = 0;
    7. voltage3v3extmax = 1;
    8. voltage3v3extmin = 0;
    9. voltage3v3intmax = 1;
    10. voltage3v3intmin = 0;
    11. voltagebattmax = 1;
    12. voltagebattmin = 0;
    13. };
    14. climate = {
    15. humidity = 14;
    16. temperature = 36;
    17. };
    18. voltages = {
    19. batt = 58428;
    20. ext3v3 = 9430;
    21. int3v3 = 6791;
    22. };
    23. };
    24. successful = 1;
    25. }
    Alles anzeigen


    Ja ich habe mein Struct mehrere male geprüft ob es sich eventuell um einen Tippfehler handelt.

    Ich hoffe ihr versteht mein Anliegen.
    Vielen Dank schonmal im voraus.

    Grüße
  • Ja da hast du recht! Ich habe den JSON Baum von der Xcode Console kopiert. Deswegen sind die mit ; getrennt.
    Original JSON:

    Quellcode

    1. {
    2. "successful": true,
    3. "health": {
    4. "alarm": {
    5. "voltage3v3intmin": false,
    6. "voltage3v3intmax": true,
    7. "voltage3v3extmin": false,
    8. "voltage3v3extmax": true,
    9. "voltagebattmin": false,
    10. "voltagebattmax": true,
    11. "temperatureMin": false,
    12. "temperatureMax": false,
    13. "humidityMax": false
    14. },
    15. "voltages": {
    16. "int3v3": 6782,
    17. "ext3v3": 10145,
    18. "batt": 58630
    19. },
    20. "climate": {
    21. "temperature": 32,
    22. "humidity": 16
    23. }
    24. }
    25. }
    Alles anzeigen
  • Ich bin eigentlich der Meinung das mein Struct zum JSON passt aber seht selbst:

    Quellcode

    1. struct HealthMainStruct:Codable {
    2. let successful:Bool
    3. let health: HealthStruct
    4. }
    5. struct HealthStruct:Codable {
    6. let alarm:Alarm
    7. let voltages: Voltages
    8. let climate:Climate
    9. }
    10. struct Voltages:Codable {
    11. let int3v3:Int
    12. let ext3v3:Int
    13. let batt:Int
    14. }
    15. struct Climate : Codable {
    16. let temperature : Double
    17. let humidity : Double
    18. }
    19. struct Alarm : Codable {
    20. let voltage3v3intmin : Bool
    21. let voltage3v3intmax : Bool
    22. let voltage3v3extmin : Bool
    23. let voltage3v3extmax : Bool
    24. let voltagebattmin : Bool
    25. let voltagebattmax : Bool
    26. let temperatureMin : Bool
    27. let temperatureMax : Bool
    28. let humidityMax : Bool
    29. }
    Alles anzeigen
  • Hm, ich würde sagen dies sieht gut aus.

    Dann könnte es vielleicht noch am Text Encoding des JSON Strings liegen.

    Alternativ bleibt noch ein Bug in JSONDecoder. Dies würde mich bei Apple aktuell nicht wirklich wundern. Da wird zwar viele entwickelt, aber wohl nur grob bis gar nicht getestet. :(
  • Habe zwar nicht deine Code zu 100% übernommen, aber Playground liefert da etwas plausibles zurück

    Quellcode

    1. //: Playground - noun: a place where people can play
    2. import Cocoa
    3. struct HealthMainStruct: Codable {
    4. let successful: Bool
    5. let health: HealthStruct
    6. }
    7. struct HealthStruct: Codable {
    8. let alarm: Alarm
    9. let voltages: Voltages
    10. let climate: Climate
    11. }
    12. struct Voltages: Codable {
    13. let int3v3: Int
    14. let ext3v3: Int
    15. let batt: Int
    16. }
    17. struct Climate: Codable {
    18. let temperature: Double
    19. let humidity: Double
    20. }
    21. struct Alarm: Codable {
    22. let voltage3v3intmin: Bool
    23. let voltage3v3intmax: Bool
    24. let voltage3v3extmin: Bool
    25. let voltage3v3extmax: Bool
    26. let voltagebattmin: Bool
    27. let voltagebattmax: Bool
    28. let temperatureMin: Bool
    29. let temperatureMax: Bool
    30. let humidityMax: Bool
    31. }
    32. let jsonData = """
    33. {
    34. "successful": true,
    35. "health": {
    36. "alarm": {
    37. "voltage3v3intmin": false,
    38. "voltage3v3intmax": true,
    39. "voltage3v3extmin": false,
    40. "voltage3v3extmax": true,
    41. "voltagebattmin": false,
    42. "voltagebattmax": true,
    43. "temperatureMin": false,
    44. "temperatureMax": false,
    45. "humidityMax": false
    46. },
    47. "voltages": {
    48. "int3v3": 6782,
    49. "ext3v3": 10145,
    50. "batt": 58630
    51. },
    52. "climate": {
    53. "temperature": 32,
    54. "humidity": 16
    55. }
    56. }
    57. }
    58. """.data(using: .utf8)!
    59. let decoder = JSONDecoder()
    60. let jsonstruct = try decoder.decode(HealthMainStruct.self, from: jsonData)
    61. print(jsonstruct)
    62. /*
    63. HealthMainStruct(successful: true, health: __lldb_expr_52.HealthStruct(alarm: __lldb_expr_52.Alarm(voltage3v3intmin: false, voltage3v3intmax: true, voltage3v3extmin: false, voltage3v3extmax: true, voltagebattmin: false, voltagebattmax: true, temperatureMin: false, temperatureMax: false, humidityMax: false), voltages: __lldb_expr_52.Voltages(int3v3: 6782, ext3v3: 10145, batt: 58630), climate: __lldb_expr_52.Climate(temperature: 32.0, humidity: 16.0)))
    64. */
    Alles anzeigen
  • Ich hab jetzt folgendes ausprobiert:

    Quellcode

    1. let dataString = String(data: data!, encoding: String.Encoding.utf8) as String!
    2. print(dataString)
    3. let testData = dataString?.data(using: String.Encoding.utf8)
    4. let jsonTest = try JSONDecoder().decode(HealthMainStruct.self, from: testData!)
    nach dem ich print(dataString) gemacht habe bekomme ich den richtigen JSON Baum mit den korrekten Werten zurück.
    Leider ist mein jsonTest mit dem JSONDecoder().decode immer noch falsch. Langsam denke ich das ich hier ein Bug gefunden habe.
  • Ich bin echt kein Swift-Experte, da ich das nur in meiner Freizeit programmiere, aber deine ? und ! scheinen mir etwas viel zu sein: dataString ist doch ein String und kein Optional. Da macht doch Optional Chaining keinen Sinn.

    Also ich kann dir sagen, wenn ich meinen vorigen Code abändere und die beiden letzten Zeilen einbaue, dann funktioniert das, wenn man auf das Optional Chaining verzichtet. Einen Bug hast Du wohl, aber dieser wird eher in deinem eigenen Code stecken. Manchmal hilft es auch eine Nacht darüber zu schlafen.

    Die Ausgabe von print(dataString) kannst Du ja aus der Console kopieren und in einem minimal Beispiel verwenden. Wenn das korrektes JSON ist, dann sollte das und wird funktionieren.
  • mufu schrieb:

    Langsam denke ich das ich hier ein Bug gefunden habe.

    Eher unwahrscheinlich.
    Deine Datenbasis ist eigentlich zu trivial, und JSONDecoder ist auf der Ebene auch ausgereift genug. (JSONDecoder hat Bugs, keine Frage, aber die sind komplexer…)

    Nichtsdestotrotz. Was in dem Fall notwendig wäre:

    A) Angaben zum Kontext
    Version des Swift-Compilers, bzw. die Xcode-Version.
    Die Plattform (iOS, MacOS, Linux,…). (JSONDecoder z.B. liegt in Foundation und da gibt es unterschiedliche Implementierungen.)

    UND

    B) Reproduzierberer Testcase
    Ein möglichst kleines Testprojekt oder ein Playground, daß den 'vermeintlichen' Bug enthält.

    Oft fällt beim Erstellen von B schon der Groschen. ;)

    manoh schrieb:

    deine ? und ! scheinen mir etwas viel zu sein

    Definitiv!
    Ich würde auch eher da das Problem vermuten.

    mufu schrieb:

    Quellcode

    1. as! HealthMainStruct

    Das ist überflüssig.

    mufu schrieb:

    Quellcode

    1. as String!

    Sorry. Das ist semantisch vollkommen falsch!

    Kann es sein, daß Du solange mit as, ! und ? planlos rumhantierst, bis der Compiler Ruhe gibt?

    Der Forced-Unwrap-Operator ! ist eine Abkürzung in zwei Situationen:

    A) Man weiß es _wirklich_ besser als der Compiler

    ODER

    B) Man spart sich ein paar Zeilen Code, um in _Beispielen_ den Blick auf das wesentliche zu lenken.

    B führt leider in der Regel dazu, daß eine Menge Copy & Paste Programmierer glauben, daß das so in Swift grundsätzlich richtig sei… *seufz*

    Mein Tip: Schreibe Deinen Code so um, daß Du ohne as und ! auskommst. Das geht. if let und guard let sind Deine Freunde. Ich bin mir ziemlich sicher, daß es dann auch klappt…^^ ;)
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • manoh schrieb:

    Ich bin echt kein Swift-Experte, da ich das nur in meiner Freizeit programmiere, aber deine ? und ! scheinen mir etwas viel zu sein: dataString ist doch ein String und kein Optional. Da macht doch Optional Chaining keinen Sinn.

    Schau mal:

    Quellcode

    1. var foo: String?
    2. var bar = foo as String!
    3. print(type(of: foo)) //Optional<String>
    4. print(type(of: bar)) //Optional<String>

    vs.

    Quellcode

    1. var foo: String?
    2. var bar = foo as! String
    3. //Fatal error: Unexpectedly found nil while unwrapping an Optional value
    4. //Forced cast from 'String?' to 'String' only unwraps optionals; did you mean to use '!'?
    5. print(type(of: foo))
    6. print(type(of: bar))
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • torquato schrieb:


    Kann es sein, daß Du solange mit as, ! und ? planlos rumhantierst, bis der Compiler Ruhe gibt?
    kann nicht sein,
    Swift ist doch so einfach, das für Einsteiger alles angenommen wird, ein rumprobieren, welches Satzzeichen man da nun in seinen Code wirft, entfällt.

    Die Anzahl der Fragen im Forum und auf anderen Seiten (Stackoverflow) ist auch signifikant gesunken.
    Ich weiß nicht immer wovon ich rede aber ich weiß das ich Recht habe. :saint:
  • nussratte schrieb:

    …ist doch so einfach, das…

    Sprache natürlich mütterlich ganz einfach. Weil wissen immer so. Jedes Baby. So seien Artikel das und Konjunktion daß ganz einfach lernen zu. ;)

    PS: Bevor jetzt jemand meckert. Einen vergbleichbaren Fehler habe ich mir oben upthread selbst erlaubt, den ich der Fairness halber nicht rauseditiere.^^

    Trotzdem zum 'Vorwurf'. In jeder Sprache gibt es semantische und syntaktische Hürden. Mir kann niemend weismachen, der sich mit C-Sprachen beschäftigt hat, niemals Probleme mit Pointern gehabt zu haben. Nach jedem Statement ein überflüssiges ; und das & hat 3 verschiedene (!) Bedeutungen. OK. Alles klar. o_O

    Swift ist m.M.n. beim Einstieg eine recht einfach zu erlernende Sprache. Die wirklichen Schwierigkeiten gehen später los. Und dann werden sie auch schwierig!
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • torquato schrieb:

    nussratte schrieb:

    …ist doch so einfach, das…
    Trotzdem zum 'Vorwurf'. In jeder Sprache gibt es semantische und syntaktische Hürden. Mir kann niemend weismachen, der sich mit C-Sprachen beschäftigt hat, niemals Probleme mit Pointern gehabt zu haben. Nach jedem Statement ein überflüssiges ; und das & hat 3 verschiedene (!) Bedeutungen. OK. Alles klar. o_O


    Swift ist m.M.n. beim Einstieg eine recht einfach zu erlernende Sprache. Die wirklichen Schwierigkeiten gehen später los. Und dann werden sie auch schwierig!

    Nein aber C hat auch nie damit geworben total einfach zu lernen zu sein....

    Switft ist um keinen Deut besser als all die anderen möchtegern einfachen Sprachen. In version 1.0 fehlen einem tausend Möglichkeiten weil ja alles "böse" ist und in den folgenden Versionen werden alles dies Möglichkeiten mit irgendwelchen grauenhaften Syntaxen eingebaut (weil war ja eigentlich gar nicht vorgesehen) und später kann die Sprache alles was man als Programmierer braucht, ist aber dann um keinen Deut einfacher zu lernen als C++ und schon gar nicht mehr performanter oder gar leserlicher....

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)