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?

Tobias
  • 32,569
  • 1
  • 34
  • 75
chaseme
  • 33
  • 3

1 Answers1

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.

db48x
  • 15,741
  • 1
  • 19
  • 23
  • 1
    Try message with `%S`. – politza Jul 21 '17 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 '17 at 16:08
  • `(setq id '\1)` – db48x Jul 27 '17 at 00:53