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