JSON
JavaScript Object Notation
https://www.w3schools.com/whatis/whatis_json.asp
JSON Syntax Rules
Data is in name/value pairs
Data is separated by commas
Curly braces hold objects
Square brackets hold arrays
example
{
"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]
}
JSON Data - A Name and a Value
JSON objects are written inside curly braces
JSON arrays are written inside square brackets
-->
https://www.w3schools.com/js/js_json_intro.asp
--
Valid Data Types
a string
a number
an object (JSON object)
an array
a boolean
a null
--
Values in JSON can be objects
{
"employee":{"name":"John", "age":30, "city":"New York"}
}
Values in JSON can be arrays
{
"employees":["John", "Anna", "Peter"]
}
--
representing inner quotes (backslash to escape)
{
"message": "He said, \"Hello, world!\""
}
FUNCTION JSON_Parse (jsonString AS STRING) AS VARIANT
' Entferne führende und nachfolgende Leerzeichen
jsonString = TRIM$(jsonString)
' Überprüfe, ob es sich um ein Objekt oder ein Array handelt
IF LEFT$(jsonString, 1) = "{" THEN
' Objekt parsen
JSON_Parse = ParseObject(jsonString)
ELSEIF LEFT$(jsonString, 1) = "[" THEN
' Array parsen
JSON_Parse = ParseArray(jsonString)
ELSE
' Wert parsen
JSON_Parse = ParseValue(jsonString)
END IF
END FUNCTION
FUNCTION ParseObject (jsonString AS STRING) AS OBJECT
' Erstelle ein leeres Objekt
DIM obj AS OBJECT
CREATE OBJECT obj
' Entferne die geschweiften Klammern
jsonString = MID$(jsonString, 2, LEN(jsonString) - 2)
' Teile den String in Schlüssel-Wert-Paare auf
DIM pairs AS STRING
pairs = SPLIT$(jsonString, ",")
' Verarbeite jedes Schlüssel-Wert-Paar
DIM i AS INTEGER
FOR i = 0 TO UBOUND(pairs)
' Teile das Paar in Schlüssel und Wert auf
DIM pair AS STRING
pair = TRIM$(pairs(i))
DIM keyValue AS STRING
keyValue = SPLIT$(pair, ":")
' Extrahiere Schlüssel und Wert
DIM key AS STRING
key = TRIM$(MID$(keyValue(0), 2, LEN(keyValue(0)) - 2))
DIM value AS STRING
value = TRIM$(keyValue(1))
' Füge den Wert dem Objekt hinzu
obj.Add key, JSON_Parse(value)
NEXT i
ParseObject = obj
END FUNCTION
FUNCTION ParseArray (jsonString AS STRING) AS VARIANT
' Erstelle ein leeres Array
DIM arr AS VARIANT
REDIM arr(0)
' Entferne die eckigen Klammern
jsonString = MID$(jsonString, 2, LEN(jsonString) - 2)
' Teile den String in Werte auf
DIM values AS STRING
values = SPLIT$(jsonString, ",")
' Verarbeite jeden Wert
DIM i AS INTEGER
FOR i = 0 TO UBOUND(values)
' Füge den Wert dem Array hinzu
arr(i) = JSON_Parse(TRIM$(values(i)))
NEXT i
ParseArray = arr
END FUNCTION
FUNCTION ParseValue (jsonString AS STRING) AS VARIANT
' Überprüfe den Datentyp des Werts
IF LEFT$(jsonString, 1) = """ THEN
' String
ParseValue = MID$(jsonString, 2, LEN(jsonString) - 2)
ELSEIF jsonString = "true" THEN
' Boolesch (wahr)
ParseValue = TRUE
ELSEIF jsonString = "false" THEN
' Boolesch (falsch)
ParseValue = FALSE
ELSEIF ISNUMERIC(jsonString) THEN
' Zahl
ParseValue = VAL(jsonString)
ELSE
' Null
ParseValue = NULL
END IF
END FUNCTION
' JSON-String
DIM jsonString AS STRING
jsonString = "{""name"": ""John Doe"", ""age"": 30, ""city"": ""New York""}"
' JSON parsen
DIM jsonObject AS OBJECT
SET jsonObject = JSON_Parse(jsonString)
' Auf Werte zugreifen
DIM name AS STRING
name = jsonObject.name
DIM age AS INTEGER
age = jsonObject.age
DIM city AS STRING
city = jsonObject.city
' Werte ausgeben
PRINT "Name: " + name
PRINT "Age: " + STR$(age)
PRINT "City: " + city
[Source: Gemini KI (https://gemini.google.com/app/35f1525de9bd6656)]
Thanks Theo, that has given me some ideas for a compact JSON parser. I can almost visualize the code.
In fact i tested Gemini and got that response.
For Charles: you can also have a Look at Here:
https://github.com/StringEpsilon/fbJson/tree/master
#include "fbJson.bi"
' JSON-Daten als String
dim as string jsonString = "{""name"": ""Max"", ""age"": 25, ""skills"": [""FreeBASIC"", ""JSON""]}"
' JSON-Daten parsen
dim as jsonItem jsonData = JsonItem(jsonString)
' Zugriff auf JSON-Elemente
print "Name: " & jsonData["name"].asString()
print "Alter: " & jsonData["age"].asInteger()
' Zugriff auf Array-Werte
dim as jsonItem skillsArray = jsonData["skills"]
for i as integer = 0 to skillsArray.count() - 1
print "Skill " & (i + 1) & ": " & skillsArray[i].asString()
next
' JSON-Daten manipulieren
jsonData["city"] = JsonItem("Berlin") ' Neues Element hinzufügen
print "Stadt: " & jsonData["city"].asString()
' Serialisieren (zurück in einen JSON-String)
print "Serialisiertes JSON: " & jsonData.toString()
Quote from: Charles Pegge on February 08, 2025, 03:27:39 PMThanks Theo, that has given me some ideas for a compact JSON parser. I can almost visualize the code.
If you can visualize code you can use that ability to create new commands that can shorten the code.
A one piece JSON parser for testing. It should be able to cope with deeply recursive JSON structures.
'JSON PARSING
'10/02/2025
'
uses console
'
'INPUT
'
string s=quote
~~~
{
"employees":[
{"firstName":"John", "lastName":"Doe", value:30.5 },
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]
}
~~~
interface
=========
'
's source strung
'
'outputs:
'
string name[1000] 'names of objects
string dat[1000] 'data of objects
int dmap[1000] 'location of name:object
int dlvl[1000] 'nesting level of objects
int je 'count of all objects
'
====================
subroutine JsonParse
====================
'
indexbase 1 'arrays lbound
int i,j
int gf,bf,be,cc,sc,db,ty,dm
int qc,qf,qe,td,tf,te,sa,sd,nc
byte*b
@b=strptr(s)-1 'byte overlay
i=0 'char iterator
j=0 'index items
sa=0 'array capture flag
sd=0 'array items flag
nc=0 'nesting depth
'
'
===================================
NextItem: 'clear flags and counters
===================================
'
j++ 'increment name / dat index
qf=0 'quote flag start
qe=0 'quote end
qc=0 'quote toggle
tf=0 'text flag
bf=0 'object flag
gf=0 'array fkag stt
cc=0 '{} object depth
sc=0 '[] array depth
td=0 'end of text flag
ty=0 'type of direct data
dm=0 'dmap assigned flag
ty=0 'raw data flgs
db=sa 'data flag
================
do 'parsing loop
================
'
@b++
i++
td=0 'assume delimiting char
'
select b 'byte pointer
'
=========
case 0 ' ' end of string
=========
'
exit do
'
=========
case 1 to 32 ' ' white space
=========
'
continue do
'
=========
case "\" 'escape char
=========
@b++ : i++ : td=1
'itr edit out '\'
if b=0 then exit do
=========
case 34 '"' quote flag toggle
=========
qc xor=1
if qc then
qf=i
else
qe=i
if gf+bf=0
if db
dat(j)=mid(s,qf+1,qe-qf-1)
if dm=0
dmap[j]=qf+1
dlvl[j]=nc
endif
goto nextitem
else
name(j)=mid(s,qf+1,qe-qf-1)
dmap[j]=qf+1
dlvl[j]=nc
dm=1
tf=0 'text flag
db=1 'data flag (expecting)
continue do
endif
endif
endif
==========
case qc<>0
==========
'
continue do 'till the quote ends
'
=========
case ","
=========
'capture unquoted data
gosub captData
if ty
goto nextitem
endif
=========
case ":"
=========
if gf+bf=0
if qf=0 then
name[j]=mid(s,tf,te-tf+1) 'raw name
dmap[j]=tf
dlvl[j]=nc
dm=1
endif
qf=0 'clear quote flag
tf=0 'text flag
db=1 'data flag (expecting)
continue do
endif
=========
case "["
=========
nc++
if db
sc++
if gf+bf=0
if sc=1 'start array
bf=i
sa=1 'array capture flag
endif
endif
else 'db=0
'splitting array into separate items
'no name assigned
name(j)=""
sd=1
endif
=========
case "]"
=========
nc--
sc--
gosub CaptData
if sc=0 'end inner array
sa=0
if ty=0
dat[j]=mid(s,bf,i-bf+1) 'brackets included
if dm=0
dmap[j]=bf
dlvl[j]=nc
endif
endif
goto nextitem
elseif sc<0
sc=0
sa=0
sd=0
if nc<=0
if ty
j++
endif
exit do 'splitting array complete
else
goto nextitem
endif
endif
=========
case "{"
=========
nc++
if sa+sd
db=1 'objects inside an array
endif
if db
cc++
if cc=1 'inner object
gf=i 'start of {} block
endif
else 'db=0
'splitting an object into parts
endif
=========
case "}"
=========
nc--
cc--
gosub CaptData
if cc=0 'end inner object
if sa=0 'not inside array
dat[j]=mid(s,gf,i-gf+1) 'brackets included
if dm=0
dmap[j]=gf
dlvl[j]=nc
endif
goto nextitem
endif
elseif cc<0
cc=0
if nc<=0
if ty
j++
endif
exit do 'splitting array complete
else
goto nextitem
endif
endif
=========
case else 'covers all other ascii
=========
td=1
if gf+bf=0
if tf=0
tf=i
'start of unquoted /
'name/number/true/flse/null
endif
te=i
endif
end select
'
'
end do 'parsing loop
SubRoutine CaptData 'internal
=============================
'
ty=0
if gf+bf+td+qf=0
if tf
if db
'unquoted data
dat[j]=mid(s,tf,te-tf+1)
if dm=0
dmap[j]=tf
dlvl[j]=nc
endif
'numbers/true/falsr/null
ty=1
endif
endif
endif
end subroutine 'CaptData
je=j-1 'set end of data
end subroutine 'JsonParse
'
'===========
'TEST OUTPUT
'===========
'
int i
print cr
gosub JsonParse
for i=1 to je
print i " NAME: " name[i] cr
print i " DATA: " dat[i] cr
next
print cr cr
'
print "split array" cr
s=dat(1)
gosub JsonParse
for i=1 to je
print i " NAME: " name[i] cr
print i " DATA: " dat[i] cr
next
print cr
print "split object" cr
s=dat(1)
gosub JsonParse
for i=1 to je
print i " NAME: " name[i] cr
print i " DATA: " dat[i] cr
next
print cr
wait
Representing 2D Arrays:
'12/02/2025
'2d array to JSON
'
dim int ar[10,10]
int x,y
'
'DATA
'
for y=1 to 10
for x=1 to 10
ar[y,x]=x-11+y*10
next
next
'
'JSON FORMAT 2D ARRAY
'
uses console
int le
string s
int i=1
string buf=nuls 100000 '100k
'
def append
le=len s
mid buf,i,s
i+=le
end def
'
s="{"+cr+" "+qu+"array"+qu+":["+cr
append
for y=1 to 10
s=" [ "
append
for x=1 to 10
s=str(ar[y,x])
if x<10
s+=","
endif
append
next
s=" ]"+cr
append
next
s=cr+" ]"+cr+"}"+cr
append
'
buf=left buf, i-1
print buf
wait
Result:
{
"array":[
[ 0,1,2,3,4,5,6,7,8,9 ]
[ 10,11,12,13,14,15,16,17,18,19 ]
[ 20,21,22,23,24,25,26,27,28,29 ]
[ 30,31,32,33,34,35,36,37,38,39 ]
[ 40,41,42,43,44,45,46,47,48,49 ]
[ 50,51,52,53,54,55,56,57,58,59 ]
[ 60,61,62,63,64,65,66,67,68,69 ]
[ 70,71,72,73,74,75,76,77,78,79 ]
[ 80,81,82,83,84,85,86,87,88,89 ]
[ 90,91,92,93,94,95,96,97,98,99 ]
]
}