Passing JSON into R function - r

I am trying to pass the following JSON into a function in R.
The raw JSON
{
"type": "Polygon",
"coordinates": [
[
[-122.68,42.77],
[-116.53,42.77],
[-116.53,44.30],
[-122.68,44.30],
[-122.68,42.77]
]
]
}
And here's the call to an R function:
myfunction(api_endpoint="my_api_endpoint", args=list(arg1 = 2000, arg2=MY_JSON_HERE)
I have tried escaping quotes, wrapping in single quotes and I keep getting errors about curly braces etc.
How do I take that literal JSON string and send it into an R function please?

With R>4.0 the new raw string syntax r"(...)" avoids the quotes / double quotes hassle:
json <- r"(
{
"type": "Polygon",
"coordinates": [
[
[-122.68,42.77],
[-116.53,42.77],
[-116.53,44.30],
[-122.68,44.30],
[-122.68,42.77]
]
]
}
)"
f <- function(json) {jsonlite::fromJSON(json)}
f(json)
$type
[1] "Polygon"
$coordinates
, , 1
[,1] [,2] [,3] [,4] [,5]
[1,] -122.68 -116.53 -116.53 -122.68 -122.68
, , 2
[,1] [,2] [,3] [,4] [,5]
[1,] 42.77 42.77 44.3 44.3 42.77
Otherwise, in this case, you could also pass json as string with simple quotes :
json <- '{
"type": "Polygon",
"coordinates": [
[
[-122.68,42.77],
[-116.53,42.77],
[-116.53,44.30],
[-122.68,44.30],
[-122.68,42.77]
]
]
}
'

The simple trick that helped me was to transform the json string, that is input into the function, via fromJSON:
myfunction <- function(json){
jsonlite::fromJSON(json)
}
That way the string is no longer interpreted as a character string, which messes things up with backslashes etc., but as an atomic list object with json structure.

Related

dealing with lists and arrays when using toJson function - in R

I am working with a pre-specified API definition, which I need to adhere to:
"myTable": {
"split": [
{
"total": 0,
"perItem": [
0,
0,
0
]
}
]
the results from my function are a list (since I am using an apply):
Export
[[1]]
[[1]]$total
[1] 13
[[1]]$perItem
1 2 3
5 7 0
but when I convert this to .json, it is not the same format as the predefined API definition:
toJSON(Export)
[{"total":[13],"perPlan":[5,7,0]}]
I was wondering how I can convert the output of the apply to have the predefined API?
I tried converting this to array:
toJSON(array(Export), simplify = TRUE)
[{"total":[13],"perPlan":[5,7,0]}]
but this still has the additional [] around the content of total.
According to the API specification your input should also "embed" your data into this split and mytable list, which can be done with:
Export <- list(list(total = 13,
perItem = c(5, 7, 0)))
for_JSON <- list(mytable = list(split = Export))
toJSON(for_JSON, simplify = TRUE, pretty = TRUE)
which gives:
{
"mytable": {
"split": [
{
"total": 13,
"perItem": [5, 7, 0]
}
]
}
}
This looks like what the API wants.

JSON nest to be removed from just one list

I have JSON content that looks like this:
myJSON = '{
"GeneralInputs":
[
{"apples":12,"pears":41},
{"apples":13,"pears":42}
],
"Assumptions":
["jabberwocky.json"]
}'
But what I need is to remove the [ and ] around ["jabberwocky.json"]
This is dictated by the use of someone else's code downstream.
I've tried ...
https://stackoverflow.com/questions/17164715/how-to-remove-a-level-of-lists-from-a-list-of-lists but this applies to all the lists.
..and ...
before = ":[\"jabberwocky.json\"]}"
after = ":\"jabberwocky.json\"}"
str_replace(myJSON, before, after)
How do I do this on just one of the two lists??
BR
Not sure how generalizable this is, but still:
library(jsonlite)
new_json <- toJSON(fromJSON(myJSON),
auto_unbox = TRUE,
pretty = TRUE)
gives:
{
"GeneralInputs": [
{
"apples": 12,
"pears": 41
},
{
"apples": 13,
"pears": 42
}
],
"Assumptions": "jabberwocky.json"
}
You can try -
before = "[\"jabberwocky.json\"]"
after = "jabberwocky.json"
stringr::str_replace(myJSON, fixed(before), after)
#In base R use sub
#sub(before, after, myJSON, fixed = TRUE)
#[1] "{\n\"GeneralInputs\":\n[\n{\"apples\":12,\"pears\":41},\n{\"apples\":13,\"pears\":42}\n],\n\n\"Assumptions\":\njabberwocky.json\n}"
Using cat for display purpose -
cat(str_replace(myJSON, fixed(before), after))
#{
#"GeneralInputs":
#[
#{"apples":12,"pears":41},
#{"apples":13,"pears":42}
#],
#
#"Assumptions":
#jabberwocky.json
#}

Convert GeoJSON to ArchGDAL geometry

When I attempt to convert a GeoJSON to an ArchGDAL geometry like seen below, I end up with a NULL Geometry. How would one convert a String GeoJSON notation to a geometry object?
using ArchGDAL
test = """{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
"properties": {"prop0": "value0"}
}
]
}"""
ArchGDAL.fromJSON(test)
# NULL Geometry
Turns out the GeoJSON can be read by simply using ArchGDAL.read(), (and, in this example extracting the first layer using ArchGDAL.getlayer())
ArchGDAL.getlayer(ArchGDAL.read(test), 0)
# Layer: OGRGeoJSON
# Geometry 0 (): [wkbPoint], POINT (102.0 0.5)
# Field 0 (prop0): [OFTString], value0

Need MS R Server API to return a dataframe in JSON row-by-row format, not column-by-column

My web developers cannot work with the JSON format generated by the MRSDeploy found in Microsoft ML Service Server.
Example:
The Data frame to be returned:
foo bar prediction
1 a .98
2 b .75
3 c .55
The PublishService code:
# Publish as service using publishService() function from
api <- publishService(
"MyPrediction_v1",
code = function_InOut,
inputs = list(foo = "numeric", bar = "character"),
outputs = list(OutputDataSet = "data.frame"),
v = version
)
The Current Return
{
"foo": [1, 2, 3],
"bar": ["a", "b", "c"]
"prediction" [.98,.75,.55]
}
The Preferred Return
{"Results": [
{
"foo": 1,
"bar":"a",
"prediction":.98
},
{
"foo": 2,
"bar":"b",
"prediction":.75
},
{
"foo": 2,
"bar":"c",
"prediction":.55
}
]
}
How do I get a row-by-row return? column-by-column is not desired?

Create output file in matlab containing numeric and string cells

I am currently working on a project where I have to program the same tool both in Matlab and R and compare both software options.
I started in R and now I am translating the code to Matlab but I am now stuck at the most important part. The output file that the tool creates after doing the analysis.
Basically, my tool makes an analysis that loops n times, and after each loop I get many variables that go into an output table. So, to be more clear, after each loop I get variables:
A = 123
B = 456
C = 'string1'
D = 'string2'
E = 789
The values in each variable change after each loop, I just want to make clear that the variables are both numeric and string values since this is what causes my problem.
In R what I do after each loop is:
outp <- cbind(A,B,C,D,E)
and create a data frame containing each variable in one cell arranged horizontally to afterwards add the result of each loop vertically in a new data frame:
outp2 <- rbind(outp2,outp)
so in the end I get a data frame (outp2) with A,B,C,D,E columns and n rows containing the values of each variable after each loop. So at the end of the looping process I can use write.csv function and create an output file of outp2 that contains both numeric and string columns.
I tried to do this in Matlab but I cannot find a function that can join the data in the same way I am doing it in R because using brackets '[]' only allows me to join numeric kind of variables. So basically my question is: How can I replicate what I am doing in R in Matlab?
I hope I was clear enough, I found it a bit hard to explain.
You can append your output with a cell array, first using curly brackets to declare your cell format (empty {} or containing your data {...}), then using brackets [...] to concatenate the output (one line after the others using ;).
out_array = {}; %initialize empty
%vertical concatenation with ";"
for ii = 1:3
out_array = [out_array; {123, 456, 'string1', 'string2', 789}];
end
This gives
out_array =
[123] [456] 'string1' 'string2' [789]
[123] [456] 'string1' 'string2' [789]
[123] [456] 'string1' 'string2' [789]
Don't now if this solves your problem, but in Matlab you can do things like
oupt = {123, 456, 'string1', 'string2', 789}
Just use curly braces instead of square brackets.
As they have said before, use curly braces to create a cell array. I imagine A, B, C, D, and E are your table headers and you already have the data that goes under them, so I'd do it like this:
outp = { A , B , C , D , E };
# This next step is only to have some data...
outp2 = magic(5);
outp2 = num2cell(outp2);
output = [ outp ; outp2 ]
output =
[123] [456] 'string1' 'string2' [789]
[ 17] [ 24] [ 1] [ 8] [ 15]
[ 23] [ 5] [ 7] [ 14] [ 16]
[ 4] [ 6] [ 13] [ 20] [ 22]
[ 10] [ 12] [ 19] [ 21] [ 3]
[ 11] [ 18] [ 25] [ 2] [ 9]

Resources