jsonian.el provides a major mode for editing JSON files of any size. The goal is to be
feature complete against json-mode with no
external dependencies or file size limits.
To that end, all functionality is guarantied to operate on arbitrarily large JSON files. If you find a feature that works only on small files, or is slower then it should be on large files, please file an issue.
jsonian.el supports standard JSON (.json) and JSON with comments (.jsonc).
jsonian.el is a single file package, and can be compiled with make build. Just move
the compiled jsonian.elc onto your load path.
If you are using Doom Emacs, you can configure
doom to use jsonian with the following snippet.
;;; In ~/.doom.d/packages.el
(package! jsonian :recipe (:host github :repo "iwahbe/jsonian"))
(package! json-mode :disable t)
;;; In ~/.doom.d/config.el
;; To enable jsonian to work with flycheck
(after! (jsonian flycheck) (jsonian-enable-flycheck))
;; To diasable so-long mode overrides
(after! (jsonian so-long) (jsonian-no-so-long-mode))Clone the repository
mkdir ~/src
cd ~/src/
git clone [email protected]:iwahbe/jsonian.gitEmacs 27+ includes so-long mode which will supplant jsonian-mode if the file has any
long lines. To prevent so-long mode from taking over from jsonian-mode, call
jsonian-no-so-long-mode after so-long mode has loaded.
Initialize the local package with use-package making it work with so-long
;;; In ~/.emacs.d/init-jsonian-mode.el
(use-package jsonian
:load-path "~/src/jsonian"
:ensure nil
:after so-long
:custom
(jsonian-no-so-long-mode))Initialize the local package with use-package making it work with
so-long, and also wrap it in an initialization package
;;; In ~/.emacs.d/init.el
(require 'init-jsonian-mode)Requires that ~/.emacs.d/site-elisp (or whichever directory the
package is in) exist and be in the load path
;;; In ~/.emacs.d/site-elisp/init-jsonian-mode.el
;;; Code:
(use-package jsonian
:load-path "~/src/jsonian"
:ensure nil
:after so-long
:custom
(jsonian-no-so-long-mode))
(provide 'init-jsonian-mode)
;;; init-jsonian-mode.el ends hereFlycheck integrates directly with
json-mode. jsonian provides the convenience
function jsonian-enable-flycheck which adds jsonian-mode to all checkers that support
json-mode. jsonian-enable-flycheck must run after flycheck has already loaded.
Return the JSON path (as a list) of POINT in BUFFER. It is assumed that BUFFER is entirely JSON and that the json is valid from POS to ‘point-min’.
For example:
{
"foo": [
{
"bar": "█"
},
{
"fizz": "buzz"
}
]
}with pos at █ should yield "[foo][0][bar]".
‘jsonian-path’ is optimized to work on very large json files (35 MiB+). This optimization is achieved by a. parsing as little of the file as necessary to find the path and b. leveraging C code whenever possible.
By default, this command is bound to C-x C-p.
Edit the string at point in another buffer. The string is expanded when being edited and
collapsed back upon exit. For example, editing the string "json\tescapes\nare\nannoying"
will drop you into a buffer containing:
json escapes
are
annoying
When you return from the buffer, the string is collapsed back into its escaped form (preserving edits).
By default, this command is bound to C-x C-s.
Move point to the enclosing node. For example:
[
{ "foo": { "fizz": 3, "buzz": 5 } },
{ "bar": { "fizz": 3, "buzz": 5 } }
]If the point started on the 5, calling jsonian-enclosing-item would move
point to the " at the beginning of "foo". Calling it again would move the
point to the first { on the second line. Calling it a final time would move
the point to the opening [.
By default, this function is bound to C-x C-e.
Provide an interactive completion interface for selecting an element in the buffer. When the element is selected, jump to that point in the buffer.
Enable ‘jsonian-mode’ for all checkers where ‘json-mode’ is enabled.
Part of the promise of jsonian is that it will be performant on large files. A
primitive benchmark is included to the Makefile. It opens a very very large
(42M) JSON file, and then forces emacs to fontify it. It finally moves point to
the end of the file and exits. Here is a comparison of the time it takes to
fontify the whole buffer on a file:
| Package | Time | comparison |
|---|---|---|
fundamental-mode |
8 seconds | 0.66 |
prog-mode |
8 seconds | 0.66 |
jsonian |
12 seconds | 1 |
javascript-mode |
31 seconds | 2.58 |
json-mode |
Fails after 43 seconds with "Stack overflow in regexp matcher" | 3.58 |
Here is what we can take away from this benchmark:
- Emacs spends 8 seconds traversing the buffer and parse matching delimiters. We
see that from the unfontified time of both
fundamental-modeandprog-mode. jsonian-modeadds 4 seconds in fontification. I assume that this time is spent in additional regex searches and function calls.javascript-modespends 19 seconds longer thejsonian-modeto achieve the same effect, presumably because the mode is more general. JavaScript is a much more complicated spec then JSON. This will result in more complicated regexes and functions.json-modeSpends 12 additional seconds, presumably with an additional set of font lock regexes.
Notes:
- Both
jsonianandjson-modewere byte-compiled for this benchmark. Byte compilingjsonianshaves 6 seconds off of this benchmark. - These benchmarks were taken on a 2.6 GHz 6-Core Intel i7 running macOS Monterey.