fukamachi / caveman

Lightweight web application framework for Common Lisp.
http://8arrow.org/caveman/
775 stars 63 forks source link

Correct way to access json object fields from POST body #54

Closed jackcarrozzo closed 9 years ago

jackcarrozzo commented 9 years ago

What's the correct way to parse pieces out of a POSTed body that arrived with application/json? I have this route:

(defroute ("/post-test/:apikey" :method :POST) (&key apikey |myobjlist|)
  (format t "post-test obj list: ~%~a~%" |myobjlist|)
  (let* ((first-obj (first |myobjlist|))
         (obj-type (type-of first-obj))
         (obj-alist (st-json::jso-alist first-obj))
         (obj-name (st-json:getjso :name first-obj)))
    (format t "first object (~a): ~a~%" obj-type first-obj)
    (format t "alist: ~a~%" obj-alist)
    (format t "name field: ~a~%" obj-name))

  (render-json '(:result "OK")))

Which I call like this:

curl -XPOST localhost:8080/post-test/1 -H "Content-type: application/json" -d '{"myobjlist":[{"name":"me","v":8},{"name":"you","v":9}]}'

That produces this response:

post-test obj list: 
(#S(ST-JSON:JSO :ALIST ((name . me) (v . 8)))
 #S(ST-JSON:JSO :ALIST ((name . you) (v . 9))))
first object (JSO): #S(ST-JSON:JSO :ALIST ((name . me) (v . 8)))
alist: ((name . me) (v . 8))
name field: NIL
127.0.0.1 - [19/Mar/2015:12:26:27 -04:00] "POST /post-test/1 HTTP/1.1" 200 15 "-" "-"

The name field returns NIL, as if the key was not found. However, doing the same thing in the REPL produces the expected action:

CL-USER> (defvar thing #S(ST-JSON:JSO :ALIST ((name . me) (v . 8)))) 
THING
CL-USER> thing
#S(ST-JSON:JSO :ALIST ((NAME . ME) (V . 8)))
CL-USER> (st-json:getjso :name thing)
ME
T
CL-USER> (st-json::jso-alist thing)
((NAME . ME) (V . 8))

What's the difference with getjso / what am I doing wrong?

jackcarrozzo commented 9 years ago

Ah, after reading [https://github.com/fukamachi/caveman/issues/22](issue #22), I found that simply doing (obj-name (getjso :|name| first-obj)) works (ie, the key name in pipes) (also added st-json to imported symbols). Why is the key different from the REPL despite the object looking exactly the same?

fukamachi commented 9 years ago

Because JSON keys are case sensitive and it is lower-cased "name". If you wanna access with :name (without vertical bars), send an HTTP request like this:

curl -XPOST localhost:8080/post-test/1 -H "Content-type: application/json" -d '{"myobjlist":[{"NAME":"me","v":8},{"NAME":"you","v":9}]}'
jackcarrozzo commented 9 years ago

Ahh got it, thanks!

On Mar 20, 2015, at 4:41 AM, Eitaro Fukamachi notifications@github.com wrote:

Because JSON keys are case sensitive and it is lower-cased "name". If you wanna access with :name (without vertical bars), send an HTTP request like this:

curl -XPOST localhost:8080/post-test/1 -H "Content-type: application/json" -d '{"myobjlist":[{"NAME":"me","v":8},{"NAME":"you","v":9}]}' — Reply to this email directly or view it on GitHub.