Page 1 of 1

Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 2:29 pm
by Quin
Hi,
I'm writing a networking application that uses JSON for its packet format. When trying to read any field from the JSON, I do something like this:

Code: Select all

  Protected Member = GetJSONMember(JSONValue(0), "type")
  If Member = 0
    ProcedureReturn #False
  EndIf
  Protected Type = GetJSONInteger(Member)
I have a lot of JSON fields though, and this gets incredibly tedious and annoying. Is there a quicker/better way?
Thanks!

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 3:39 pm
by boddhi
Functions such as ExtractJSONxxxx() can be used for this purpose.
Can you give a more detailed example of your JSON structure?

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 3:45 pm
by Quin
No, ExtractJSON* I don't think will work. I get a packet like:

Code: Select all

{"type": 1, "name": "Quin", "message": "Hello world!"}
I want to get the type field if it exists, check it, and if it's 1 for example, extract the JSON fields for the name and message. But if I just extract them with GetJSONString(GetJSONMember(JSONValue(0), "name")) it crashes if the field doesn't exist. I thought about extracting to a map and using FindMapElement() but that seems almost more messy.

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 4:08 pm
by wombats
GetJSONMember will return 0 if the member doesn't exist, so you can use it to check if a member exists, unless I'm missing something.

You can also loop through the members:

Code: Select all

Global jsonStr.s = ~"{\"type\": 1, \"name\": \"Quin\", \"message\": \"Hello world!\"}"

Global json = ParseJSON(#PB_Any, jsonStr)
Global jsonVal = JSONValue(json)

If ExamineJSONMembers(jsonVal)
  While NextJSONMember(jsonVal)
    Select JSONMemberKey(jsonVal)
        
      Case "type" :
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_Number
          Debug GetJSONInteger(JSONMemberValue(jsonVal))
        EndIf
      Case "name"
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_String
          Debug GetJSONString(JSONMemberValue(jsonVal))
        EndIf
      Case "message"
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_String
          Debug GetJSONString(JSONMemberValue(jsonVal))
        EndIf
        
    EndSelect
  Wend
EndIf

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 4:10 pm
by boddhi
And this ?

Code: Select all

Structure MEMBERDETAIL
  type.q
  name.s
  message.s
EndStructure

Define.MEMBERDETAIL Member
JSON.s="{"+Chr(34)+"type"+Chr(34)+": 1, "+Chr(34)+"name"+Chr(34)+": "+Chr(34)+"Quin"+Chr(34)+", "+Chr(34)+"message"+Chr(34)+": "+Chr(34)+"Hello world!"+Chr(34)+"}"
; UnescapeString seems corrupted on PB610bX
                          
ParseJSON(0,JSON)
ExtractJSONStructure(JSONValue(0),@Member.MEMBERDETAIL,MEMBERDETAIL)
With Member
  If \type=0 ; Or any other test
    ClearStructure(@Member,MEMBERDETAIL)
  Else
    Debug \type
    Debug \name
    Debug \message
  EndIf
EndWith

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 4:44 pm
by Quin
wombats wrote: Thu Jan 18, 2024 4:08 pm GetJSONMember will return 0 if the member doesn't exist, so you can use it to check if a member exists, unless I'm missing something.

You can also loop through the members:

Code: Select all

Global jsonStr.s = ~"{\"type\": 1, \"name\": \"Quin\", \"message\": \"Hello world!\"}"

Global json = ParseJSON(#PB_Any, jsonStr)
Global jsonVal = JSONValue(json)

If ExamineJSONMembers(jsonVal)
  While NextJSONMember(jsonVal)
    Select JSONMemberKey(jsonVal)
        
      Case "type" :
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_Number
          Debug GetJSONInteger(JSONMemberValue(jsonVal))
        EndIf
      Case "name"
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_String
          Debug GetJSONString(JSONMemberValue(jsonVal))
        EndIf
      Case "message"
        If JSONType(JSONMemberValue(jsonVal)) = #PB_JSON_String
          Debug GetJSONString(JSONMemberValue(jsonVal))
        EndIf
        
    EndSelect
  Wend
EndIf
Checking it against 0 is what I do currently, but I was wondering if there's something cleaner than having that littering my code.

Re: Easily validating if JSON fields exist?

Posted: Thu Jan 18, 2024 4:45 pm
by Quin
boddhi wrote: Thu Jan 18, 2024 4:10 pm And this ?

Code: Select all

Structure MEMBERDETAIL
  type.q
  name.s
  message.s
EndStructure

Define.MEMBERDETAIL Member
JSON.s="{"+Chr(34)+"type"+Chr(34)+": 1, "+Chr(34)+"name"+Chr(34)+": "+Chr(34)+"Quin"+Chr(34)+", "+Chr(34)+"message"+Chr(34)+": "+Chr(34)+"Hello world!"+Chr(34)+"}"
; UnescapeString seems corrupted on PB610bX
                          
ParseJSON(0,JSON)
ExtractJSONStructure(JSONValue(0),@Member.MEMBERDETAIL,MEMBERDETAIL)
With Member
  If \type=0 ; Or any other test
    ClearStructure(@Member,MEMBERDETAIL)
  Else
    Debug \type
    Debug \name
    Debug \message
  EndIf
EndWith
Oh, a structure! This is exactly what I was looking for, thanks!