Search code examples
jsonracket

How do I serialize an object into JSON including defined variables in Racket?


I am trying to to write a json structure to a file using racket. The actual function for writing works fine but when creating the data structure which I write to the file, I simply cannot figure out how to include values from bound variables.

    (start_location . "h")
    (end_location . "t")
    (ETA . 30)
    (route . ("g"))
    (optional_parameters . #hasheq((accessibility . #f)))
))

(define write-json-wrapper (lambda (jsexpr filename)
    (call-with-output-file filename (lambda (x) (write-json jsexpr x)) #:exists 'replace)
))  

The above structure works when I write it to the file.

(define x "h")
(define b #hasheq(
    (start_location . x)
    (end_location . "t")
    (ETA . 30)
    (route . ("g"))
    (optional_parameters . #hasheq((accessibility . #f)))
))```

However when I try to use the value stored in x as the value for start_location it throws an error.

write-json: expected argument of type <legal JSON value>; given: 'x

Any help or explanation would be much appreciated.

Solution

  • #hasheq is literal for hash table and its content isn't evaluated:

    #hasheq((a . 5) (b . 7)) reads equal to (make-...eq '((b . 7) (a . 5)))

    If you want to use values of variables, you have to use make-hasheq like this:

    #lang racket
    (require json)
    
    (define x 1)
    (define y 2)
    (define z 3)
    
    (define jsexpr
      (make-hasheq (list (cons 'x x)
                         (cons 'y y)
                         (cons 'z z))))
    
    (define write-json-wrapper (lambda (jsexpr filename)
        (call-with-output-file filename
          (lambda (x) (write-json jsexpr x)) #:exists 'replace))) 
    

    Example:

    (write-json-wrapper jsexpr "foo.txt")
    

    If you're familiar with quasiquote, you can do also this:

    (define jsexpr
      (make-hasheq `((x . ,x)
                     (y . ,y)
                     (z . ,z))))
    

    So for your data:

    (make-hasheq `((start_location . ,x)
                     (end_location . "t")
                     (ETA . 30)
                     (route . ("g"))
                     (optional_parameters . #hasheq((accessibility . #f)))))