* [[https://newbedev.com/how-to-hook-emacs-up-to-a-json-service][How to hook emacs up to a json service? | Newbedev]] :website: [2021-12-18 Sat 14:37] ** Article *** How to hook emacs up to a json service? Emacs has pretty good built-in support for this kind of thing, at least at the basic level of making requests and parsing responses. Use =url-retrieve= or =url-retrieve-synchronously= to fetch data from a remote service. As the names suggest, one is an asynchronous call which takes a callback, the other a blocking call which returns a buffer containing the response. Load them by including =(require 'url)= in your Elisp file. The =url-= functions are documented in a separate Info manual from the rest of Elisp, named "URL", but some useful features go unmentioned there. For GET requests where arguments are passed in the URL, the =url-build-query-string= function is useful for constructing a string of query parameters from an a-list of keys and values. For POST, PUT, DELETE and other requests, you may need to let-bind the variables =url-request-data=, =url-request-method= and =url-request-extra-headers=. They have informative docstrings. A final confusing thing about using these calls for HTTP URLs is that they leave the HTTP response headers in the same buffer as the response body, which may not be what you expect. A simple way to deal with this is to use the (undocumented) =url-http-end-of-headers= variable to skip over the headers before processing the body, though I suspect there might be better ways. Use the =json-read= function to parse JSON responses, and bind the variables =json-array-type=, =json-object-type=, and =json-key-type= to control how JSON types are converted to Lisp types. This function is obtained by including =(require 'json)=. XML responses can be parsed using =xml-parse-region= or =libxml-xml-parse-region=. The latter requires Emacs to be compiled with libxml support, the former is implemented in Elisp. Putting this together, the skeleton of a request to a JSON service looks something like this: #+begin_example (url-retrieve "http://example.com/api/some/request" (lambda (events) (goto-char url-http-end-of-headers) (let ((json-object-type 'plist) (json-key-type 'symbol) (json-array-type 'vector)) (let ((result (json-read))) ;; Do something with RESULT here )))) #+end_example In the callback, you can work with =result= like any other Lisp value. The =plist-get=, =pcase= and =cl-destructuring-bind= functions are often useful for extracting pieces of the result. Use =(require 'pcase)= to get the =pcase= macro, =(require 'cl-lib)= to get =cl-destructuring-bind=. \\ This is what I use to lookup currency exchange rates from a json webservice at rate-exchange.appspot.com: #+begin_example (defun my-json-get (url) (interactive) (progn (require 'json) (with-current-buffer (url-retrieve-synchronously url) (goto-char (point-min)) (re-search-forward "^$") (json-read)))) (defun my-currency-exchange-rate (from to) (let ((xurl (format "http://rate-exchange.appspot.com/currency?from=%s&to=%s" from to))) (assoc-default 'rate (my-json-get xurl)))) #+end_example Example usage: #+begin_example (my-currency-exchange-rate "USD" "SEK") #+end_example