JSON Helper
I wrote a helper get-json-value
to extract values from json output produced by cl-json.
(defun property-p (property)
(funcall #'consp property))
(defun get-property-value (property)
(funcall #'cdr property))
(defun get-property-key (property)
(funcall #'car property))
(defun json-object-p (json)
(and (listp json) (every #'consp json)))
(defun json-array-p (json)
(and (listp json) (every json-object-p json)))
(defun json-p (json)
(or (json-object-p json) (json-array-p json)))
(defun get-json-value (keys json)
(princ (list keys json))
(terpri)
(cond
((null keys) json)
((json-p json)
(let ((key (car keys)))
(if (numberp key)
(get-json-value (cdr keys) (nth key json))
(let ((property
(find-if
#'(lambda (property)
(and (property-p property)
(eq (get-property-key property) (car keys)))) json)))
(if property
(get-json-value (cdr keys) (get-property-value property)))))))
(t nil)))
For example, a json object produced by cl-json looks something like this:
((NUMBER . 7)
(MESSAGE . success)
(PEOPLE
((NAME . Mark Vande Hei) (CRAFT . ISS))
((NAME . Oleg Novitskiy) (CRAFT . ISS))
((NAME . Pyotr Dubrov) (CRAFT . ISS))
((NAME . Thomas Pesquet) (CRAFT . ISS))
((NAME . Megan McArthur) (CRAFT . ISS))
((NAME . Shane Kimbrough) (CRAFT . ISS))
((NAME . Akihiko Hoshide) (CRAFT . ISS))))
To extract the list of people, we supply the path (:people)
:
(get-json-value `(:people) json)
To extract the first person in the list of people, we extend the path to include an index:
(get-json-value `(:people 0) json)
To get the name of the first person in the list of people, we can further extend the path:
(get-json-value `(:people 0 :name) json)