3

I loaded some json data into a string and have elisp parsing it using the json-read-from-string function. Now I want to do is access data from the JSON by key. When I print out the data via message, it looks kind of like a list of lists (with arrays too!), so I assumed that the regular association list functions would work on the data, however this does not seem to be the case.

Here is a sample code that I am trying to debug:

(require 'request)
(require 'json)
(require 'cl)

(setq json-string "{\"1\": [{\"id\": 2,\"attribute\": \"salutation\",\"displayName\": \"Salutation\",\"category\": 1},{\"id\": 4,\"attribute\": \"middlename\",\"displayName\": \"Middle Name\",\"category\": 1},{\"id\": 6,\"attribute\": \"suffix\",\"displayName\": \"Suffix\",\"category\": 1},{\"id\": 8,\"attribute\": \"city\",\"displayName\": \"City\",\"category\": 1},{\"id\": 9,\"attribute\": \"state\",\"displayName\": \"State\",\"category\": 1},{\"id\": 11,\"attribute\": \"email\",\"displayName\": \"Email\",\"category\": 1},{\"id\": 12,\"attribute\": \"telephone\",\"displayName\": \"Telephone\",\"category\": 1},{\"id\": 10,\"attribute\": \"zipCode\",\"displayName\": \"Zip Code\",\"category\": 1},{\"id\": 13,\"attribute\": \"telephoneExtension\",\"displayName\": \"Telephone Extension\",\"category\": 1},{\"id\": 7,\"attribute\": \"streetAddress\",\"displayName\": \"Street Address\",\"category\": 1},{\"id\": 3,\"attribute\": \"firstName\",\"displayName\": \"First Name\",\"category\": 1},{\"id\": 1,\"attribute\": \"fullName\",\"displayName\": \"Full Name\",\"category\": 1},{\"id\": 5,\"attribute\": \"lastName\",\"displayName\": \"Last Name\",\"category\": 1},{\"id\": 14,\"attribute\": \"notes\",\"displayName\": \"Notes\",\"category\": 1}],\"2\": [{\"id\": 15,\"attribute\": \"name\",\"displayName\": \"Name\",\"category\": 2},{\"id\": 16,\"attribute\": \"address\",\"displayName\": \"Address\",\"category\": 2},{\"id\": 17,\"attribute\": \"phone\",\"displayName\": \"Phone\",\"category\": 2},{\"id\": 18,\"attribute\": \"email\",\"displayName\": \"email\",\"category\": 2},{\"id\": 19,\"attribute\": \"url\",\"displayName\": \"URL\",\"category\": 2}],\"3\": [{\"id\": 20,\"attribute\": \"name\",\"displayName\": \"Name\",\"category\": 3},{\"id\": 21,\"attribute\": \"address\",\"displayName\": \"address\",\"category\": 3},{\"id\": 22,\"attribute\": \"county\",\"displayName\": \"County\",\"category\": 3},{\"id\": 23,\"attribute\": \"state\",\"displayName\": \"State\",\"category\": 3},{\"id\": 24,\"attribute\": \"zipcode\",\"displayName\": \"Zip Code\",\"category\": 3},{\"id\": 25,\"attribute\": \"pin\",\"displayName\": \"PIN\",\"category\": 3},{\"id\": 26,\"attribute\": \"longitude\",\"displayName\": \"Longitude\",\"category\": 3},{\"id\": 27,\"attribute\": \"latitude\",\"displayName\": \"Latitude\",\"category\": 3}]}")
  
(setq tester (json-read-from-string json-string))

;;(message "%s" tester)
;; This looks like: ((1 . [((id . 2) (attribute . salutation) (displayName . Salutation) (category . 1)) ((id . 4) (attribute . middlename) (displayName . Middle Name) (category . 1)) ((id . 6) (attribute . suffix) (displayName . Suffix) (category . 1)) ((id . 8) (attribute . city) (displayName . City) (category . 1)) ((id . 9) (attribute . state) (displayName . State) (category . 1)) ((id . 11) (attribute . email) (displayName . Email) (category . 1)) ((id . 12) (attribute . telephone) (displayName . Telephone) (category . 1)) ((id . 10) (attribute . zipCode) (displayName . Zip Code) (category . 1)) ((id . 13) (attribute . telephoneExtension) (displayName . Telephone Extension) (category . 1)) ((id . 7) (attribute . streetAddress) (displayName . Street Address) (category . 1)) ((id . 3) (attribute . firstName) (displayName . First Name) (category . 1)) ((id . 1) (attribute . fullName) (displayName . Full Name) (category . 1)) ((id . 5) (attribute . lastName) (displayName . Last Name) (category . 1)) ((id . 14) (attribute . notes) (displayName . Notes) (category . 1))]) (2 . [((id . 15) (attribute . name) (displayName . Name) (category . 2)) ((id . 16) (attribute . address) (displayName . Address) (category . 2)) ((id . 17) (attribute . phone) (displayName . Phone) (category . 2)) ((id . 18) (attribute . email) (displayName . email) (category . 2)) ((id . 19) (attribute . url) (displayName . URL) (category . 2))]) (3 . [((id . 20) (attribute . name) (displayName . Name) (category . 3)) ((id . 21) (attribute . address) (displayName . address) (category . 3)) ((id . 22) (attribute . county) (displayName . County) (category . 3)) ((id . 23) (attribute . state) (displayName . State) (category . 3)) ((id . 24) (attribute . zipcode) (displayName . Zip Code) (category . 3)) ((id . 25) (attribute . pin) (displayName . PIN) (category . 3)) ((id . 26) (attribute . longitude) (displayName . Longitude) (category . 3)) ((id . 27) (attribute . latitude) (displayName . Latitude) (category . 3))]))

(message "%s" (assoc '1 tester))
;; => nil

Using assoc, alist-get, assq all seem to return nil in the last line.

Is there a different function that I need to use? Or do I just have to loop through the data myself to find the data that I want?

2
  • (message "%S" tester) gives me ((\1 . [((id . 2) (attribute . "salutation") .... BTW, you miss a } at the end of json-string .
    – Ynjxsjmh
    Jan 23, 2021 at 5:54
  • @Ynjxsjmh I've added the missing }.
    – Tobias
    Dec 28, 2021 at 5:00

1 Answer 1

3

Cute.

Take a look at the beginning of the alist again:

((1 . [((id . 2) (attribute . salutation)…

It looks like the key is a number, so I tried that

(assoc 1 tester)
nil

It doesn't have any quotes, but maybe a string?

(assoc "1" tester)
nil

Nope. It's actually a symbol whose name is the single digit 1:

(assoc '\1 tester)
(\1 . [((id . 2)…

When I printed out the whole tester object I also saw the \; I'm not sure why it's not printed that way in your example code. One thing that I like about Common Lisp is that symbols with unusual names get "quoted" with vertical bars; that would help a lot in this situation, since the keys would be |1|, |2|, etc.

3
  • 1
    Try message with %S.
    – politza
    Jul 21, 2017 at 20:45
  • Thanks! That works. How would you go about storing '\1 inside a variable to pass into assoc? I have a integer in a variable, but I don't know how to convert that to the correct symbol. I tried: (setq id 1) (setq idsym (make-symbol (number-to-string id))) (message "%S" (assoc idsym tester)) to no avail.
    – chaseme
    Jul 26, 2017 at 16:08
  • (setq id '\1)
    – db48x
    Jul 27, 2017 at 0:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.