jsonlite icon indicating copy to clipboard operation
jsonlite copied to clipboard

Control indent in toJSON?

Open MichaelChirico opened this issue 3 years ago • 5 comments

I am trying to match a JSON emitter that uses a different indent than toJSON does by default, e.g.

# in /tmp/tmp.json
{
 "array": [
  {
   "key1": "val1",
   "key2": null,
   "key3": {},
   "key4": []
  }
 ]
}

then in R:

l = jsonlite::read_json('/tmp/tmp.json')
l$array[[1]]$key1 = "newVal"

toJSON(l, auto_unbox = TRUE, null = 'null', pretty = TRUE)
{
  "array": [
    {
      "key1": "newVal",
      "key2": null,
      "key3": {},
      "key4": []
    }
  ]
} 

This is very close to what i want, except the indenting is off -- since the file is SVN tracked, a huge diff shows up. Ignoring whitespace is not an option.

Using prettify also gets close, but unfortunately, it breaks the formatting of the empty entries at key3 and key4:

prettify(toJSON(l, auto_unbox = TRUE, null = 'null'), indent=1)
{
 "array": [
  {
   "key1": "newVal",
   "key2": null,
   "key3": {

   },
   "key4": [

   ]
  }
 ]
}

Is there some combination of options that I'm missing that will allow the indentation of the prettify() option but the cell formatting of the toJSON(pretty = TRUE) option?

MichaelChirico avatar Jun 16 '21 04:06 MichaelChirico

I don't think you can, but maybe you can fix the spaces aftewards like so:

gsub("  ", " ", toJSON(l, pretty=T), fixed = T)

jeroen avatar Jun 16 '21 07:06 jeroen

That will also remove any non-indent spaces with that pattern unfortunately. I suspect there's no pure gsub way to do it.

I hacked something like ws <- regexpr("^ +", j); substring(j, pmax(attr(ws, "match.length") / 2 + 1, 1)) to get it done but it's quite messy. Would it make sense to expose indent as an option in toJSON directly?

MichaelChirico avatar Jun 16 '21 07:06 MichaelChirico

I think it will be very hard to match the formatting of an arbitrary other implementation, you will probably run into other inconsistencies for more complex json structures.

The only unambiguous way is to minify() on all ends.

jeroen avatar Jun 16 '21 07:06 jeroen

Do you consider the difference in expanding {} for prettify vs not doing so for toJSON(pretty=TRUE) to be a bug?

MichaelChirico avatar Jun 16 '21 08:06 MichaelChirico

No, both are correct. The package has two different prettify methods, one that is done when serializing R to json (pretty=T), and another one prettify() that is provided by the C library that just re-indents existing json. \

If you want clean diffs, you either need to minify all the things, or use some external json formatter/linter that you run before each commit, just like you would for C++ code.

jeroen avatar Jun 16 '21 08:06 jeroen

Thanks, the discussion above is enough for me.

MichaelChirico avatar Apr 04 '23 17:04 MichaelChirico