ivan
ivan

Reputation: 6322

R to JSON: trouble embedding an array

I'm converting some data from R to JSON using jsonlite.

The desired output would look like:

[
  {
    "data": {
      "name": "foo",
      "moogs": [
        {
          "x": 1,
          "y": 2
        },
        {
          "x": 2,
          "y": 1
        }
      ]
    }
  }
]

I'm struggling with the embedded array value for moogs. The closest I've come to a solution is to serialize it:

[
  {
    "data": {
      "name": "foo",
      "moogs": "[{\"x\":1,\"y\":2},{\"x\":2,\"y\":1}]"
    }
  }
]

The data comes from foo.R:

name = "foo"

mtx = matrix(rep(0, 4), ncol=2, nrow=2)
mtx[1, 2] = 1
mtx[2, 1] = 1

The conversion does the following:

library(jsonlite)
source("foo.R")

moogs = data.frame()
for(x in 1:nrow(mtx)) {
  for(y in 1:ncol(mtx)) {
    if(mtx[x, y] == 1) {
      moogs = rbind(moogs, data.frame(x=x, y=y))
    }
  }
}

data = fromJSON('[{}]')
data$name = name
data$moogs = toJSON(moogs)

container = fromJSON('[{}]')
container$data = data

print(toJSON(container, pretty=TRUE))

If I change

data$moogs = toJSON(moogs)

to

data$moogs = moogs

I get the following error:

Error in `$<-.data.frame`(`*tmp*`, moogs, value = list(x = 1:2, y = 2:1)) :
  replacement has 2 rows, data has 1

Is it possible to produce the embedded array?

Upvotes: 1

Views: 77

Answers (2)

alistaire
alistaire

Reputation: 43354

If you mimic the nesting with lists (and data frames, which are lists), you can create a single R object that can be converted directly:

mtx <- matrix(c(0, 1, 1, 0), 2, dimnames = list(NULL, c('x', 'y')))
mtx
#>      x y
#> [1,] 0 1
#> [2,] 1 0

x <- list(data = list(name = 'foo', moogs = as.data.frame(mtx)))
str(x)
#> List of 1
#>  $ data:List of 2
#>   ..$ name : chr "foo"
#>   ..$ moogs:'data.frame':    2 obs. of  2 variables:
#>   .. ..$ x: num [1:2] 0 1
#>   .. ..$ y: num [1:2] 1 0

jsonlite::toJSON(x, auto_unbox = TRUE, pretty = TRUE)
#> {
#>   "data": {
#>     "name": "foo",
#>     "moogs": [
#>       {
#>         "x": 0,
#>         "y": 1
#>       },
#>       {
#>         "x": 1,
#>         "y": 0
#>       }
#>     ]
#>   }
#> }

Upvotes: 3

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84709

You need dataframes with list columns. Do:

data = data.frame(name=name, moogs=I(list(moogs))) 
container = data.frame(data = I(data))

Then:

> toJSON(container, pretty = TRUE)
[
  {
    "data": {
      "name": "foo",
      "moogs": [
        {
          "x": 1,
          "y": 2
        },
        {
          "x": 2,
          "y": 1
        }
      ]
    }
  }
] 

Upvotes: 1

Related Questions