Home > Software design >  Recreating a data structure from jsonlite::fromJSON to be used with jsonlite::toJSON
Recreating a data structure from jsonlite::fromJSON to be used with jsonlite::toJSON

Time:03-01

I have some JSON data I've pulled in using jsonlite::fromJSON():

raw.content <- jsonlite::fromJSON("https://raw.githubusercontent.com/danwild/leaflet-velocity/master/demo/wind-gbr.json")

the structure of which ends up being:

> str(raw.content)
'data.frame':   2 obs. of  2 variables:
 $ header:'data.frame': 2 obs. of  13 variables:
  ..$ parameterUnit      : chr  "m.s-1" "m.s-1"
  ..$ parameterNumber    : int  2 3
  ..$ dx                 : num  1 1
  ..$ dy                 : num  1 1
  ..$ parameterNumberName: chr  "eastward_wind" "northward_wind"
  ..$ la1                : num  -7.5 -7.5
  ..$ la2                : num  -28.5 -28.5
  ..$ parameterCategory  : int  2 2
  ..$ lo2                : num  156 156
  ..$ nx                 : int  14 14
  ..$ ny                 : int  22 22
  ..$ refTime            : chr  "2017-02-01 23:00:00" "2017-02-01 23:00:00"
  ..$ lo1                : num  143 143
 $ data  :List of 2
  ..$ : num  0 0 0 0 0 0 0 0 0 0 ...
  ..$ : num  0 0 0 0 0 0 0 0 0 0 ...

I need to be able to turn some data back into this format so that I can use jsonlite::toJSON() to get it back into the same JSON format is the example data above.

The problem: I've never seen this data structure before. It's a data.frame contain 2 obs of 2 vars, where the first is a data.frame and the second is a list. Other than a data frame containing a nested list (which the header does not seem to be), how does a data frame contain a data frame?

The data I have is in standard tibble (or data.frame) format, so I need to get from that back to that data structure. Using the example data above to start with tibbles, what I've tried (among many, many others:

data <- raw.content$data
header <- raw.content$header

> str(data.frame(header, data))
'data.frame':   308 obs. of  15 variables:
 $ parameterUnit                                                     : chr  "m.s-1" "m.s-1" "m.s-1" "m.s-1" ...
 $ parameterNumber                                                   : int  2 3 2 3 2 3 2 3 2 3 ...
 $ dx                                                                : num  1 1 1 1 1 1 1 1 1 1 ...
 $ dy                                                                : num  1 1 1 1 1 1 1 1 1 1 ...
 $ parameterNumberName                                               : chr  "eastward_wind" "northward_wind" "eastward_wind" "northward_wind" ...
 $ la1                                                               : num  -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 ...
 $ la2                                                               : num  -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 ...
 $ parameterCategory                                                 : int  2 2 2 2 2 2 2 2 2 2 ...
 $ lo2                                                               : num  156 156 156 156 156 156 156 156 156 156 ...
 $ nx                                                                : int  14 14 14 14 14 14 14 14 14 14 ...
 $ ny                                                                : int  22 22 22 22 22 22 22 22 22 22 ...
 $ refTime                                                           : chr  "2017-02-01 23:00:00" "2017-02-01 23:00:00" "2017-02-01 23:00:00" "2017-02-01 23:00:00" ...
 $ lo1                                                               : num  143 143 143 143 143 143 143 143 143 143 ...
 $ c.0..0..0..0..0..0..0..0..0..0..0..0..0..0..0..4.17000007629395.. : num  0 0 0 0 0 0 0 0 0 0 ...
 $ c.0..0..0..0..0..0..0..0..0..0..0..0..0..0..0...3.88000011444092..: num  0 0 0 0 0 0 0 0 0 0 ...
Warning message:
In data.frame(header, data) :
  row names were found from a short variable and have been discarded

data.x <- data[[1]]
data.y <- data[[2]]

newdata <- vector(mode = "list", length = 2)

newdata[[1]] <- data.x
newdata[[2]] <- data.y

> str(data.frame(header, newdata))
'data.frame':   308 obs. of  15 variables:
 $ parameterUnit                                                     : chr  "m.s-1" "m.s-1" "m.s-1" "m.s-1" ...
 $ parameterNumber                                                   : int  2 3 2 3 2 3 2 3 2 3 ...
 $ dx                                                                : num  1 1 1 1 1 1 1 1 1 1 ...
 $ dy                                                                : num  1 1 1 1 1 1 1 1 1 1 ...
 $ parameterNumberName                                               : chr  "eastward_wind" "northward_wind" "eastward_wind" "northward_wind" ...
 $ la1                                                               : num  -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 -7.5 ...
 $ la2                                                               : num  -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 -28.5 ...
 $ parameterCategory                                                 : int  2 2 2 2 2 2 2 2 2 2 ...
 $ lo2                                                               : num  156 156 156 156 156 156 156 156 156 156 ...
 $ nx                                                                : int  14 14 14 14 14 14 14 14 14 14 ...
 $ ny                                                                : int  22 22 22 22 22 22 22 22 22 22 ...
 $ refTime                                                           : chr  "2017-02-01 23:00:00" "2017-02-01 23:00:00" "2017-02-01 23:00:00" "2017-02-01 23:00:00" ...
 $ lo1                                                               : num  143 143 143 143 143 143 143 143 143 143 ...
 $ c.0..0..0..0..0..0..0..0..0..0..0..0..0..0..0..4.17000007629395.. : num  0 0 0 0 0 0 0 0 0 0 ...
 $ c.0..0..0..0..0..0..0..0..0..0..0..0..0..0..0...3.88000011444092..: num  0 0 0 0 0 0 0 0 0 0 ...
Warning message:
In data.frame(header, newdata) :
  row names were found from a short variable and have been discarded

As you can see both of these produce a single data frame, rather than a data frame containing a data frame and a list.

CodePudding user response:

You can put both items in a list then set the attributes manually:

header <- raw.content$header
data   <- raw.content$data

result <- list(header, data)
attributes(result) <- list(names = c("header", "data"),
                           class = "data.frame",
                           row.names = 1:2)
str(result)
#> 'data.frame':    2 obs. of  2 variables:
#>  $ header:'data.frame':  2 obs. of  13 variables:
#>   ..$ parameterUnit      : chr  "m.s-1" "m.s-1"
#>   ..$ parameterNumber    : int  2 3
#>   ..$ dx                 : num  1 1
#>   ..$ dy                 : num  1 1
#>   ..$ parameterNumberName: chr  "eastward_wind" "northward_wind"
#>   ..$ la1                : num  -7.5 -7.5
#>   ..$ la2                : num  -28.5 -28.5
#>   ..$ parameterCategory  : int  2 2
#>   ..$ lo2                : num  156 156
#>   ..$ nx                 : int  14 14
#>   ..$ ny                 : int  22 22
#>   ..$ refTime            : chr  "2017-02-01 23:00:00" "2017-02-01 23:00:00"
#>   ..$ lo1                : num  143 143
#>  $ data  :List of 2
#>   ..$ : num  0 0 0 0 0 0 0 0 0 0 ...
#>   ..$ : num  0 0 0 0 0 0 0 0 0 0 ...

Created on 2022-02-28 by the reprex package (v2.0.1)

  • Related