Search code examples
rpurrrjsonlite

toJSON without outer square brackets


I am converting a nested list of a specific structure (required by an API) to JSON using toJSON() in jsonlite. However, I need the final JSON to not contain the outer square brackets (also required by an API).

test_list <- list(
    list(formName = "test_title", user_id = "test_userid", rows = list(list(row = 0))), 
    list(formName = "test_title2", user_id = "test_userid2", rows = list(list(row = 0)))
)

jsonlite::toJSON(test_list, pretty = TRUE, auto_unbox = TRUE)

Which gives:

[
  {
    "formName": "test_title",
    "user_id": "test_userid",
    "rows": [
      {
        "row": 0
      }
    ]
  },
  {
    "formName": "test_title2",
    "user_id": "test_userid2",
    "rows": [
      {
        "row": 0
      }
    ]
  }
] 

But I need to remove the first and last square bracket.

I can use purrr::flatten() to remove the top level of the list and thus the square brackets in the JSON, but then toJSON() doesn't seem to like that the list has duplicate names, and renames them to name.1, name.2, name.3 etc (which also isn't allowed by the API).

That is:

jsonlite::toJSON(test_list %>% purrr::flatten(), pretty = TRUE, auto_unbox = TRUE)

Which removes the outer square brackets, but converts the names in the second element to formName.1, user_id.1, rows.1, like so:

{
  "formName": "test_title",
  "user_id": "test_userid",
  "rows": [
    {
      "row": 0
    }
  ],
  "formName.1": "test_title2",
  "user_id.1": "test_userid2",
  "rows.1": [
    {
      "row": 0
    }
  ]
}

But this is what I need:

{
  "formName": "test_title",
  "user_id": "test_userid",
  "rows": [
    {
      "row": 0
    }
  ],
  "formName": "test_title2",
  "user_id": "test_userid2",
  "rows": [
    {
      "row": 0
    }
  ]
}

That is, formName, user_ud and rows in the second JSON element are not appended with ".1"

Any advice would be greatly appreciated!


Solution

  • Just edit the JSON. You can do it with gsub, or with stringr. If you use stringr functions, it will lose it's "json" class, but you can put it back:

    > x = jsonlite::toJSON(test_list %>% purrr::flatten(), pretty = TRUE, auto_unbox = TRUE)
    > gsub("user_id\\.1", "user_id", x)
    {
      "formName": "test_title",
      "user_id": "test_userid",
      "rows": [
        {
          "row": 0
        }
      ],
      "formName.1": "test_title2",
      "user_id": "test_userid2",
      "rows.1": [
        {
          "row": 0
        }
      ]
    }
    
    > y = stringr::str_replace_all(x, "user_id\\.1", "user_id")
    > class(y) = "json"
    > y
    {
      "formName": "test_title",
      "user_id": "test_userid",
      "rows": [
        {
          "row": 0
        }
      ],
      "formName.1": "test_title2",
      "user_id": "test_userid2",
      "rows.1": [
        {
          "row": 0
        }
      ]
    } 
    

    I'll leave it to you to write appropriate regex to make the substitutions you want.