2

Here is a minimal example of an org-table:

#+NAME: radar
|----------+------|
| Variable |  Val |
|----------+------|
| Red      | 43.3 |
| Blue     | 83.1 |
| Yellow   | 86.4 |
|----------+------|

I would like to convert such a table to the following JSON format:

[
  ['Variable', 'Val'],
  ['Red', 43.3],
  ['Blue', 83.1],
  ['Yellow', 86.4]
]
4
  • 1
    This answer describes a quick method to convert to CSV. Unfortunately, there is no orgtbl-to-json but if you look at the definitions of orgtbl-to-csv and orgtbl-to-generic, you might be able to come up with your own orgtbl-to-json.
    – NickD
    Mar 30 at 2:35
  • have you included the column headers in the results string, on purpose?
    – Saravana
    Mar 30 at 13:16
  • @Saravana, yes, it's compliant with echarts' dataset format (apache.github.io/echarts-handbook/en/concepts/dataset).
    – crocefisso
    Mar 30 at 13:54
  • @NickD, thank you for your advice. As you can see, I almost found the solution. I was wondering if it was possible to add "orgtbl-to-json" to the formats list in the org-table-export function located in org-table.el from my init. I.e. without having to manually modify org-table.el, so when an Emacs update is installed, "orgtbl-to-json" is automatically added.
    – crocefisso
    Mar 30 at 20:18

3 Answers 3

2

Here's an implementation of orgtbl-to-json along the lines of my comment. It's enough for your simple case and for the purposes of the Echart model you linked to:

* Table

#+NAME: radar
|----------+------+---------+-------|
| Variable | Val1 |    Val2 | Val 3 |
|----------+------+---------+-------|
| Red      | 43.3 |   82.13 | 78.22 |
| Blue     | 83.1 |     9.6 |   9.8 |
| Yellow   | 86.4 | 133.465 |  27.5 |
|----------+------+---------+-------|

* Code

#+begin_src elisp :var x=radar :results drawer
  (defun orgtbl-to-json (table params)
    "Convert the `orgtbl-mode' TABLE to JSON material."
    (orgtbl-to-generic
     table
     (org-combine-plists '(
                           :sep ", "
                           :tstart "[" :tend "]"
                           :lstart "  [" :lend "],"
                           :llstart "  [" :llend "]"
                           :fmt (lambda (x)
                                  (let ((y (org-babel--string-to-number x)))
                                    (if y (format "%g" y)
                                      (format "\"%s\"c" x)))))
                         params)))
            
  (orgtbl-to-json x nil)
#+end_src


#+RESULTS:
:results:
[
  ["Variable", "Val1", "Val2", "Val 3"],
  ["Red", 43.3, 82.13, 78.22],
  ["Blue", 83.1, 9.6, 9.8],
  ["Yellow", 86.4, 133.465, 27.5]
]
:end:

EDIT: changed the single quotes to double quotes - apparently, JSON string syntax uses double quotes only as delimiters.

3
#+NAME: radar
|----------+------|
| Variable |  Val |
|----------+------|
| Red      | 43.3 |
| Blue     | 83.1 |
| Yellow   | 86.4 |
|----------+------|

#+begin_src emacs-lisp :exports results :results value  :var table=radar
  (thread-last table                    ; (org-table-to-lisp)
               (seq-map
                (lambda (it)
                  (seq-into it 'vector)))
               json-encode)          
#+end_src

#+RESULTS:
: [["Variable","Val"],["Red",43.3],["Blue",83.1],["Yellow",86.4]]

This seems like a good starting point

(thread-last
  "|----------+------|
| Variable |  Val |
|----------+------|
| Red      | 43.3 |
| Blue     | 83.1 |
| Yellow   | 86.4 |
|----------+------|
"
  org-table-to-lisp
  (seq-filter (lambda (it)
        (not (eq it 'hline))))
  (seq-map
   (lambda (it)
     (thread-last it
          (seq-map (lambda (it)
                 (or (org-babel--string-to-number it)
                 it)))
          (pcase--flip seq-into 'vector))))
  (pcase--flip seq-into 'vector)
  json-encode
  insert)

This uses dash

(->>
 "|----------+------|
| Variable |  Val |
|----------+------|
| Red      | 43.3 |
| Blue     | 83.1 |
| Yellow   | 86.4 |
|----------+------|
"
 org-table-to-lisp
 (--filter (not (eq it 'hline)))
 (--map
  (->> it
       (--map (or (org-babel--string-to-number it)
                  it))
       (apply 'vector)))
 (apply 'vector)
 json-encode
 insert)
[["Variable","Val"],["Red",43.3],["Blue",83.1],["Yellow",86.4]]
[["Variable","Val"],["Red",43.3],["Blue",83.1],["Yellow",86.4]]
3
  • I get the error error: (void-function thread-last) on emacs 26.3
    – Saravana
    Mar 30 at 8:40
  • 1
    (require 'subr-x) (require 'seq) (require 'pcase)
    – mxnt
    Mar 30 at 9:08
  • 1
    I updated with a dash equivalent ...
    – mxnt
    Mar 30 at 9:18
1

Here are some additions on how to implement NickD's solution.

  1. Put orgtbl-to-json function somewhere in your init.
  (defun orgtbl-to-json (table params)
    "Convert the `orgtbl-mode' TABLE to JSON material."
    (orgtbl-to-generic
     table
     (org-combine-plists '(
               :sep ", "
                :tstart "[" :tend "]"
                :lstart "  [" :lend "],"
                :llstart "  [" :llend "]"
                :fmt (lambda (x)
                       (let ((y (org-babel--string-to-number x)))
                     (if y (format "%g" y)
                       (format "'%s'" x)))))
             params)))
  1. set the TABLE_EXPORT_FORMAT property to orgtbl-to-json :
:PROPERTIES:
:TABLE_EXPORT_FILE: ~/tmp/tmp.json
:TABLE_EXPORT_FORMAT: orgtbl-to-json
:END:
|----------+------|
| Variable |  Val |
|----------+------|
| Red      | 43.3 |
| Blue     | 83.1 |
| Yellow   | 86.4 |
|----------+------|
  1. Put the cursor within the table and do M-x org-table-export.
8
  • You are also missing commas. See my answer.
    – NickD
    Mar 30 at 22:07
  • Indeed, thank you, your function is perfect. I just added some explanations on how I implemented it.
    – crocefisso
    Mar 30 at 23:20
  • The fact that I cannot do a json-read the "desired output value" suggests that you either misunderstand json syntax or json-read is something wrong ... There is a reason why the result of my snippet is different from what you have requested, and the reason being that what you claim as json is not really json. Btw, copy your json output to a file demo.json, turn on flycheck-mode and do M-x flycheck-list-errors and it will show file.json 2 4 error Expecting value (json-python-json). Btw, I know nothing about json or javascript.
    – mxnt
    Mar 31 at 2:53
  • As mentioned in the question comments, the output format is called Dataset by Echarts documentation (apache.github.io/echarts-handbook/en/concepts/dataset). As to whether it can be called JSON, I'm not 100% sure, but from my understanding, it seems to be compliant with JSON specifications (see json.org/json-en.html). If I'm wrong we can edit the references to JSON and replace them with references to Echart dataset.
    – crocefisso
    Mar 31 at 9:57
  • 1
    Oh, I see, that's why you edited your answer, replacing ' by ". Echart's handles " as well. Maybe Echarts uses JSON5 (json5.org) instead of JSON, which is an extension of JSON that accepts simple quotes.
    – crocefisso
    Apr 1 at 22:09

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.