I would like to manage a JSON config file with added comments on some key-value-pairs and explain options. Since it is not possible to comment in JSON, I thought about using org-mode literate programming and tangle to manage the file.

Questions are:

  • there is no specific JSON code block, because JSON is not really a language. Which language block should I use instead?
  • Can I tangle code parts to one single JSON file? Does tangleing insert characters like return between two blocks?
  • is there a smarter way to manage / comment JSON files in a literate kind of way?

Here is a way to do this with literate programming in org.

#+BEGIN_SRC json :tangle config.json
{"key1": "value",

For key2 I prefer 0 instead of 1

#+BEGIN_SRC json  :tangle config.json
 "key2": 0}

Here we automate tangling, and then show it is valid json.

#+BEGIN_SRC emacs-lisp  :var tangle=(org-babel-tangle)
(json-read-file "config.json")

: ((key1 . value) (key2 . 0))

Is there a smarter way? I guess it depends on where you want your comments. You could use elisp to do it like this.

#+BEGIN_SRC emacs-lisp
(let ((data '((key-1 . value)
          ;; I like another-value for key-2
          (key-2 . another-value))))
  (with-temp-file "config-2.json"
    (insert (json-encode data))))

(json-read-file "config-2.json")

You could also use noweb, and define your own execute function like this.

#+BEGIN_SRC emacs-lisp
(defun org-babel-execute:config-json (body params)
  (message "%S" params)
  (let* ((vars (seq-filter (lambda (x) (eq (car x) :var)) params))
     (config (cl-loop for var in vars
              if (eq (car (cdr var)) 'config)
              return (cddr var))))
    (with-temp-file config (insert (org-babel-expand-body:generic body params)))))

: org-babel-execute:config-json

#+name: key-value-1
#+BEGIN_SRC config-json
"key1": 0

#+name: key-value-2
#+BEGIN_SRC config-json
"key2": 1

When you "execute" this block it will write out config3.json.

#+name: config
#+BEGIN_SRC config-json :noweb yes :var config="config3.json" 
{<<key-value-1>>, <<key-value-2>>}

#+RESULTS: config

#+BEGIN_SRC sh :results raw
cat config3.json

{"key1": 0, "key2": 1}
  • Wow, a lot of possibilities, thank you for the effort! I will try them out. The verification part is clever, too. Line breaks between blocks do not seem to be an issue then. – breathe_in_breathe_out Jan 25 at 8:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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