Iterating over a string in Vimscript or Parse a JSON file

The simplest solution with the least dependencies is just using the json_decode vim function.

let dict = json_decode(jsonString)

Even though Vim's origin dates back a lot it happens that its internal string() eval() representation is that close to JSON that its likely to work unless you need special characters.

You can lookup the implementation here which even supports true/false/null if you want: https://github.com/MarcWeber/vim-addon-json-encoding

Better use that library (vim-addon-manager allows to install dependencies easily). Now it depends on your data whether this is good enough.

Now Benjamin Klein posted your question to vim_use which is why I'm replying. Best and fast replies happen if you subscribe to the Vim mailinglist. Goto vim.sf.net and follow the community link. You cannot expect the Vim community to scrape stackoverflow.

I've added the keyword "json" and "parsing" to that little code that it can be found easier.

If this solution does not work for you you can try the many :h if_* bindings or write an external script which extracts the information you're looking for, or turns JSON into Vim's dictionary representation which can be read by eval() escaping special characters you care about correctly.


If you seek for completely correct solution omitting dependencies is one of the worst thing you can do. The eval() variant mentioned by @MarcWeber is one of the fastest, but it has its disadvantages:

  1. Using solution for securing eval I mentioned in comment makes it no longer the fastest. In fact after you use this it makes eval() slower by more then an order of magnitude (0.02s vs 0.53s in my test).
  2. It does not respect surrogate pairs.
  3. It cannot be used to verify that you have correct JSON: it accepts some strings (e.g. "\<C-o>") that are not JSON strings and it allows trailing commas.
  4. It fails to give normal error messages. It fails badly if you use vam#VerifyIsJSON I mentioned in p.1.
  5. It fails to load floating point values like 1e10 (vim requires numbers to look like 1.0e10, but numbers like 1e10 are allowed: note “and/or” in the first paragraph).

. All of the above (except for the first) statements also apply to vim-addon-json-encoding mentioned by @MarcWeber because it uses eval. There are some other possibilities:

  1. Fastest and the most correct is using python: pyeval('json.loads(vim.eval("varname"))'). Not faster then eval, but fastest among other possibilities. (0.04 in my test: approximately two times slower then eval())

    Note that I use pyeval() here. If you want solution for vim version that lacks this functionality it will no longer be one of the fastest.

  2. Use my json.vim plugin. It has an advantages of slightly better error reporting compared to failed vam#VerifyIsJSON, slightly worse compared to eval() and it correctly loads floating-point numbers. It can be used for verification of strings (it does not accept "\<C-a>"), but it loads lists with trailing comma just fine. It does not support surrogate pairs. It is also very slow: in the test I used (it uses 279702 character long strings) it takes 11.59s to load. Json.vim tries to use python if possible though.
  3. For the best error reporting you can take yaml.vim and purge YAML support out of it leaving only JSON (I once have done the same thing for pyyaml, though in python: see markedjson library used in powerline: it is pyyaml minus YAML stuff plus classes with marks). But this variant is even slower then json.vim and should only be used if the main thing you need is error reporting: 207 seconds for loading the same 279702 character long string.

Note that the only variant mentioned that satisfies both requirements “no dependencies” and “no python” is eval(). If you are not fine with its disadvantages you have to throw away one or both of these requirements. Or copy-paste code. Though if you take speed into account only two candidates are left: eval() and python: if you want to parse json fast you really must use C and only these solutions spend most time in functions written in C.

Most other interpreters (ruby/perl/TCL) do not have pyeval() equivalent so they will be slower even if their JSON implementation is written in C. Some other (lua/racket (mzscheme)) have pyeval() equivalent, but e.g. luaeval('{}') is zero meaning that you will have to add additional step explicitly and recursively converting objects into vim dictionaries and lists (e.g. luaeval('vim.dict({})')) which will impact performance. Cannot say anything about mzeval(), but I have never heard about anybody actually using racket (mzscheme) with vim.