Page 1 of 1

cl-json

Posted: Fri Jan 29, 2016 5:34 pm
by jakep
Greetings. I am attempting to use CL-JSON. I have successfully used the CL-JSON list decoder, but want to use the CLOS decoder instead. The example provided in the CL-JSON manual works for me. But when I try the code below, all of the slots in the returned CLOS object are unbound. I didn't expect that; what am I doing wrong?

The json that I am trying to access is library catalog data from my librarything.com account. I can set up a link or otherwise supply the json input, if required.

I did RTFM, by the way. But I admit my CLOS is a bit rusty, and frankly I did not really grok what the documentation was trying to tell me.

Here is what I did in emacs/slime with clozure common lisp as my CL:

Code: Select all

CL-USER> (ql:quickload :cl-json)
To load "cl-json":
  Load 1 ASDF system:
    cl-json
; Loading "cl-json"

(:CL-JSON)
CL-USER> (json:set-decoder-simple-clos-semantics)
#<Compiled-function JSON:DECODE-JSON #x30200112BF6F>
CL-USER> (setf *jsf* (open "librarything_thierrygar-1.json"))
#<BASIC-FILE-CHARACTER-INPUT-STREAM ("librarything_thierrygar-1.json"/5 UTF-8) #x3020012969DD>
CL-USER> (setf *json-clos* (json:decode-json *jsf*))
#<An instance of #<JSON:FLUID-CLASS NIL> #x302001479E4D>
CL-USER> (inspect *json-clos*)
[0]     #<An instance of #<JSON:FLUID-CLASS NIL> #x3020012E5D9D>
[1]     Class: #<JSON:FLUID-CLASS NIL>
[2]     Wrapper: #<CCL::CLASS-WRAPPER NIL #x3020012E70DD>
        Instance slots
[3]     :LF: #<Unbound>
[4]     :FL: #<Unbound>
[5]     :|0|: #<Unbound>
[6]     :|2|: #<Unbound>
[7]     :CODE: #<Unbound>
[8]     :|1|: #<Unbound>
[9]     :TEXT: #<Unbound>
[10]    :BOOKS--ID: #<Unbound>
[11]    :TITLE: #<Unbound>
[12]    :SORTCHARACTER: #<Unbound>
[13]    :PUBLIC: #<Unbound>
[14]    :PRIMARYAUTHOR: #<Unbound>
[15]    :SECONDARYAUTHOR: #<Unbound>
[16]    :AUTHORS: #<Unbound>
[17]    :COLLECTIONS--ID-A: #<Unbound>
[18]    :COLLECTIONS: #<Unbound>
Inspect> 

Re: cl-json

Posted: Sat Jan 30, 2016 6:29 am
by Goheeca
After a little bit of experimentation, I come with this:

Code: Select all

; SLIME 2014-12-23
CL-USER> (ql:quickload :cl-json)
To load "cl-json":
  Load 1 ASDF system:
    cl-json
; Loading "cl-json"
[package json]....................................
[package json-rpc]................
(:CL-JSON)
CL-USER> (json:set-decoder-simple-clos-semantics)
#<FUNCTION JSON:DECODE-JSON>
CL-USER> (inspect (json:decode-json-from-string "[{\"a\":1},{\"b\":2}]"))

The object is a VECTOR of length 2.
0. #<#<JSON:FLUID-CLASS NIL {2425C459}> {244AEB59}>
1. #<#<JSON:FLUID-CLASS NIL {2425C459}> {244AEF39}>
> 0

The object is a STANDARD-OBJECT of type #<JSON:FLUID-CLASS NIL {2425C459}>.
0. A: 1
1. B: "unbound"
> :u

The object is a VECTOR of length 2.
0. #<#<JSON:FLUID-CLASS NIL {2425C459}> {244AEB59}>
1. #<#<JSON:FLUID-CLASS NIL {2425C459}> {244AEF39}>
> 1

The object is a STANDARD-OBJECT of type #<JSON:FLUID-CLASS NIL {2425C459}>.
0. A: "unbound"
1. B: 2
> :q

; No value
CL-USER> 
The JSON objects are decoded into the fluid-objects which theirs class is the same, if the keys are not present then the corresponding symbols are unbound. Fluid-objects have the set of slots equal to union of sets of keys in every JSON object decoded, it is consistent with:
that it has at least the slots named by the keys in D (which are decoded to symbols in the usual manner); and that in F these slots are bound to Lisp images of the corresponding JSON Values, and any other slot is unbound

Re: cl-json

Posted: Sat Jan 30, 2016 8:19 am
by jakep
Well, thanks for replying. But as it stands I have absolutely no idea how to go about using this. When I decode the json of interest, I have no idea how to access any content in the returned object. If I am being dense about this please suggest which part of the cl-json documentation might enlighten me.

Re: cl-json

Posted: Sun Jan 31, 2016 4:36 am
by Goheeca
If you want iterate over the keys in CLOS objects you'd need MOP. However I'd go for hashtables and setup cl-json this way:

Code: Select all

(json:set-decoder-simple-clos-semantics)
(setf json:prototype nil)
(multiple-value-setq (json:*beginning-of-object-handler*
                      json:*object-key-handler*
                      json:*object-value-handler*
                      json:*end-of-object-handler*)
  (let ((table)
        (key))
    (values (lambda () (setf table (make-hash-table :test #'equal)))
            (lambda (input) (setf key input))
            (lambda (input) (setf (gethash key table) input))
            (lambda () table))))
For the iteration over the keys you can use the loop macro, the maphash function or the with-hash-table-iterator macro