Easily validating if JSON fields exist?

Just starting out? Need help? Post your questions and find answers here.
Quin
Addict
Addict
Posts: 1136
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Easily validating if JSON fields exist?

Post 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!
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: Easily validating if JSON fields exist?

Post by boddhi »

Functions such as ExtractJSONxxxx() can be used for this purpose.
Can you give a more detailed example of your JSON structure?
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Quin
Addict
Addict
Posts: 1136
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Easily validating if JSON fields exist?

Post 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.
wombats
Enthusiast
Enthusiast
Posts: 720
Joined: Thu Dec 29, 2011 5:03 pm

Re: Easily validating if JSON fields exist?

Post 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
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: Easily validating if JSON fields exist?

Post 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
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Quin
Addict
Addict
Posts: 1136
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Easily validating if JSON fields exist?

Post 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.
Quin
Addict
Addict
Posts: 1136
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Easily validating if JSON fields exist?

Post 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!
Post Reply