Seite 1 von 1

JSON parsen

Verfasst: 16.05.2022 06:20
von SieGeL2k22
Hallo Community,

ich versuche gerade eine JSON Antwort von einem Server zu parsen, aber irgendwie stelle ich mich da zu doof an :(

Evtl. kann mir da ja mal jemand auf die Sprünge helfen? Es geht um folgende JSON Struktur:

Code: Alles auswählen

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJJbm9Db3JlIiwiaWF0IjoxNjUyNjc0MzY2LCJleHAiOjE2NTI2Nzc5NjYsImF1ZCI6InB1cmViYXNpY0Bsb2NhbGhvc3QiLCJ1aWQiOjh9.q66RWqH3iBJsCuAdJ_XCLjWSj7i3BJhs3gmB4MC1KBk",
    "expires": {
        "date": "2022-05-16 07:12:46.098796",
        "timezone_type": 3,
        "timezone": "Europe/Berlin"
    },
    "user": {
        "id": 8,
        "email": "purebasic@localhost",
        "firstname": "Pure",
        "lastname": "Basic",
        "login_count": 115,
        "last_login": "2022-05-16 06:12:29.409009",
        "failed_login_date": null,
        "create_date": "2022-05-15 22:23:11.800488",
        "is_daemon": 0
    }
}
Wie kann ich direkt auf die einzelnen Elemente unterhalb von "expires" und "user" zugreifen? Auf "token" kann ich problemlos zugreifen, aber irgendwie raffe ich das nicht, wie man auf die Unterelemente der "expires" bzw. "user" Elemente zugreifen soll...

Meine bisherigen Ansätze scheitern immer daran, dass einige Felder leer sind??

Hier mein Code:

Code: Alles auswählen

Structure ICTExpires
  date.s
  timezone_type.l
  timezone.s
EndStructure  

Structure ICTUser
  id.l
  email.s
  firstname.s
  lastname.s
  login_count.l
  last_login.s
  failed_login_date.s
  create_date.s
  is_daemon.l
EndStructure  

Structure ICT
  token.s
  Map expires.ICTExpires()
  Map user.ICTUser()
EndStructure


HttpRequest = HTTPRequest(#PB_HTTP_Post,BASE$, "["+Chr(34)+"todo.all"+Chr(34)+"]", #PB_HTTP_Debug|#PB_HTTP_NoSSLCheck, Header$());
If HttpRequest
  HttpCode.s = HTTPInfo(HTTPRequest, #PB_HTTP_StatusCode)
  HttpResponse = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
  FinishHTTP(HTTPRequest)
  
  ParseJSON(0,HttpResponse)
  ObjectValue = JSONValue(0)
  NewMap Expires.ICTExpires()
  NewMap User()
  NewMap UL.ICTUser()  
  NewMap ICT.ICT()
 Token.s = GetJSONString(GetJSONMember(JSONValue(0),"token"))

ExtractJSONMap(JSONValue(0),ICT())

Debug ICT()\expires()\date

ExtractJSONMap(GetJSONMember(JSONValue(0),"expires"),Expires())
ExtractJSONMap(GetJSONMember(JSONValue(0),"user"),User())
ExtractJSONMap(GetJSONMember(JSONValue(0),"user"),UL())

Debug "DATE: " + Expires()\date
Debug "TZ-TYPE: " + Expires()\timezone_type
Debug "TZ: " + Expires()\timezone
;Debug user("email")
;Debug Token



Else
  Debug "Request creation failed"
EndIf
Debug "---------------------------------------------"
Debug(HttpResponse);
Sobald ich auf die Unterlemente zugreifen will (z.B. ICT()\expires()\date) sind die immer leer?

Nutze ich "ExtractJSONMap(GetJSONMember(JSONValue(0),"user"),User())" - also eine leere Map - sind alle Integer Fields leer.

Definiere ich die Map "User()" als "User.s()", sind die Textfields vorhanden, dafür aber die Integerfelder nicht mehr?

Kann mir da evtl. mal jemand helfen, meinen Knoten im Kopf zu lösen?

Vielen Dank schon mal im Vorraus!

Re: JSON parsen

Verfasst: 16.05.2022 07:46
von Bisonte
Es klappt nicht, da es keine maps sind...

ich gehe davon aus, dass die oben genannte json struktur das ist, was bei dem http-request rauskommt, also immer ein datensatz.
daher ist es keine map sondern ganz banal nur eine struktur.

Code: Alles auswählen

Structure s_expires
  date.s
  timezone_type.i
  timezone.s
EndStructure
Structure s_user
  id.i
  email.s
  firstname.s
  lastname.s
  login_count.i
  last_login.s
  failed_login_date.s
  create_date.s
  is_daemon.i
EndStructure

Structure myStructure
  token.s
  expires.s_expires
  user.s_user
EndStructure

Procedure.i LoadJSONFile(File$, *Var.myStructure, Flag = #PB_JSON_NoCase)
  
  Protected jV, jSon = LoadJSON(#PB_Any, File$, Flag)
  Protected Result = #False
  
  If jSon
    jV = JSONValue(jSon)
    ExtractJSONStructure(jV, *Var, myStructure)
    Result = #True
    FreeJSON(jSon)
  EndIf
  
  ProcedureReturn Result
  
EndProcedure

Define a.myStructure

LoadJSONFile("R:\test.json",@a)

Debug a\user\email

Re: JSON parsen

Verfasst: 16.05.2022 20:21
von SieGeL2k22
@Bisonte:

Erst mal Danke für Deine schnelle Antwort!

Habe das gerade getestet und nun klappt das auch!

Ich habe in der Anleitung von json immer ein Json Object als Map gleich gesetzt, da war ich wohl schon zu müde :)

Nochmals Danke für Deine Hilfe!

Re: JSON parsen

Verfasst: 17.05.2022 11:21
von TroaX
Generell gibt das JSON nicht genau vor, in was für eine Art Strukturtyp das ganze zu behandeln ist. Das Problem an der Stelle war nicht, das es keine Map laut JSON ist (was JSON nicht vorgibt), sondern das die Werte der Schlüssel unterschiedlichsten Typs sind. Eine Map, Liste oder ein Array müssen immer einen festen Typ haben. Entweder ein primitiver Datentyp (Integer, Long, String etc.) oder eine Struktur als Typ. Wenn also alle Werte vom Typ String gewesen wären, dann hätte es auch als Map geklappt. Was noch interessant wäre, ob die JSON-Lib bei der Nutzung als Map oder List mit dem Typ String die Zahlen automatisch zu einem String konvertiert. Das müsste ich nachher mal testen. Sonst ist JSON eine ziemlich eklige Angelegenheit mit PB

Re: JSON parsen

Verfasst: 17.05.2022 11:45
von SieGeL2k22
Also ich hatte das ja zuerst mit den Maps probiert, da war es dann halt so, dass die Integer Werte bei Nutzung einer string-basierten Map allesamt leer waren.
Mir war nicht bewusst, das eine Map immer einen gleichen Datentyp haben muss?!
Ich hatte das eher wie einen Key-Value Speicher angesehen, der unabhängig vom Datentyp arbeitet (so wie z.B. bei PHP die assoziativen Arrays).

Aber Danke noch mal für die Erklärung, das werde ich mir auf alle Fälle merken!

Re: JSON parsen

Verfasst: 17.05.2022 18:55
von TroaX
Alle Elemente einer Map sind vom Typ bei der Initialisierung. Erstellst du eine String-Map, sind auch alle Elemente der Map vom Typ String. Ohne Angabe eines Typs müsste sie immer vom Typ Integer sein. Ein Test bzgl. Autocast kann ich mir nach einem kurzen Blick in die Hilfe sparen:
Wenn der JSON-Wert Elemente enthält, die nicht den richtigen Typ haben, um mit der Map() übereinzustimmen, dann werden sie ignoriert und das zugehörige Map-Element bleibt leer.
Das ist im Grunde das, was du beobachtet hast. Es ist also nicht ganz trivial, mit den Maps zu hantieren.