JSON voor de microbit#
Speciale (minimale) json-library voor microbit
JSON is een string-formaat voor ojecten (dictionaries), dat veel gebruikt wordt voor de uitwisseling van objecten tussen verschillende systemen.
(micro)Python heeft een ingebouwde JSON-library, met functies
json.loads(s: str) -> dict
- van JSON-string naar Python object (dictionary)json.dumps(d: dict) -> str
- van Python object (dictionary) naar JSON string.
Helaas is deze standaard-library niet beschikbaar in micro:bit Python. Hieronder volgt een eenvoudige implementatie van deze JSON-library, voldoende voor de micro:bit gateway.
Syntax voor eenvoudige JSON:
value : dictionary ; array ; simple .
simple: string ; number ; boolean .
string: '"', non-quote-seq, '"'.
int: digit-seq .
bool: 'false' ; 'true' .
dict: '{', keyvalue list option, '}' .
keyvalue: string, ':', value.
array: '[', value list option, ']' .
Hieronde het bestand json.py
zoals gebruikt in de gateway.
JSON module code#
def loads(data: str):
eof = chr(0)
ch = data[0]
pos = 0
def error():
raise Exception
def nextch():
nonlocal pos, ch
pos = pos + 1
if pos < len(data):
ch = data[pos]
else:
ch = eof
return
def skipblanks():
while ch == ' ' or ch == '\n' or ch == '\r' or ch == '\t':
nextch()
def accept(c: str):
if ch != c:
error()
nextch()
skipblanks()
def value():
skipblanks()
if ch == '{':
return dictionary({})
elif ch == '[':
return array([])
elif ch == '"':
return string()
elif '0' <= ch and ch <= '9':
return number()
elif ch == 'f' or ch == 't':
return boolean()
else:
error()
def keyvalue(items: dict):
key = string()
accept(':')
val = value()
items[key] = val
return items
def dictionary(items: dict):
accept('{')
if ch != '}':
items = keyvalue(items)
while ch == ',':
accept(',')
items = keyvalue(items)
accept('}')
return items
def array(items: list):
accept('[')
if ch != ']':
items.append(value())
while ch == ',':
accept(',')
items.append(value())
accept(']')
return items
def string():
accept('"')
value = ''
while ch != '"':
value += ch
nextch()
accept('"')
return value
def number():
value = ''
while '0' <= ch and ch <= '9':
value += ch
nextch()
skipblanks()
return int(value)
def boolean():
value = ''
while 'a' <= ch and ch <= 'z':
value += ch
nextch()
skipblanks()
if value == 'true':
return True
elif value == 'false':
return False
else:
error()
return value()
def dumps(val: dict) -> str:
# transform Python `int` keys to JSON `string` keys
def to_json_keys (obj: dict) -> dict:
new_obj = {}
for key in obj:
value = obj[key]
if type(value) is dict:
value = to_json_keys(value)
if type(key) is int:
new_obj[str(key)] = value
else:
new_obj[key] = value
return new_obj
return str(to_json_keys(val)).replace("'", '"')
Testen#
import json
# voor vergelijking met de officiële versie
json1 = '{ "aap": 10, "noot": {"mies": false, "teun": [1,2,3], "vuur": [ { } ] }}'
loads(json1)
{'aap': 10, 'noot': {'mies': False, 'teun': [1, 2, 3], 'vuur': [{}]}}
json.loads(json1) == loads(json1)
True
json2 = '{"nodeid": "fe3d", "counter": 3027, "payload": {"0": {"temperature": 235}, "1": {"barometer": 10093}, "2": {"dOut": 1}, "8": {"aOut": 255}}}'
loads(json2)
{'nodeid': 'fe3d',
'counter': 3027,
'payload': {'0': {'temperature': 235},
'1': {'barometer': 10093},
'2': {'dOut': 1},
'8': {'aOut': 255}}}
loads(json2) == json.loads(json2)
True
json3 = dumps(loads(json2))
json3
'{"nodeid": "fe3d", "counter": 3027, "payload": {"0": {"temperature": 235}, "1": {"barometer": 10093}, "2": {"dOut": 1}, "8": {"aOut": 255}}}'
json.dumps(json.loads(json2)) == dumps(loads(json2))
True