2

I want to send a post request with a few variables in the body, using the httr package.

What the body would look like if it was in JSON format:

{a:"1", b:"2", c:[{d:"3", e:"4"}]}

What I tried with httr::POST()

r <- POST("http://httpbin.org/post", body = list(a = 1, b = 2, c = list(d=3, e=4)))

The error I got:

Error in curl::handle_setform(handle, .list = req$fields) : 

Unsupported value type for form field 'c'.

How would I need to structure my POST() statement to send it in the format that I want mentioned above?

EDIT: On trying @renny's solution (I added verbose() for viewability) i.e. the following line

r <- POST("http://httpbin.org/post", body = json_array, encode="json", verbose())

I am able to observe that the JSON that's generated in the output is of the following format:

{"post":{"a":1,"b":2,"c":{"d":3,"e":4}}}

As you can see, the "c" variable does not have [] around it and there is a "post" variable. The following is what I want.

{"a":1,"b":2,"c":[{"d":3,"e":4}]}
jerome
  • 91
  • 7

3 Answers3

3

I know it is an old question, but maybe someone will end up here like me. The problem was a missing list.

To create a json array instead of an object, list must be unnamed. So in your example:

> json_array <- list(a = 1, b = 2, c = list(list(d=3, e=4)))

> jsonlite::toJSON(json_array)
{"a":[1],"b":[2],"c":[{"d":[3],"e":[4]}]}

# auto_unbox extracts values from unnecessary arrays, not explicit lists
> jsonlite::toJSON(json_array, auto_unbox = T)
{"a":1,"b":2,"c":[{"d":3,"e":4}]} 

Then you will not need to use jsonlite, since encode does the work:

httr::POST("http://httpbin.org/post", body = json_array, encode="json")

returning the response

{
  "args": {}, 
  "data": "{\"a\":1,\"b\":2,\"c\":[{\"d\":3,\"e\":4}]}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "application/json, text/xml, application/xml, */*", 
    "Accept-Encoding": "deflate, gzip", 
    "Content-Length": "33", 
    "Content-Type": "application/json", 
...
}

Adrià
  • 356
  • 2
  • 7
2
library(httr)

 json_array <- list(
      post =  list(a = 1, b = 2, c = list(d=3, e=4))
    )

 r <- POST("http://httpbin.org/post", body = json_array, encode="json")

app_data <- content(r)

Try this. This might work out!

renny
  • 590
  • 4
  • 23
  • @SJEROMEGIDEON If you remove the assignment of list from "post", then it won't appear. eg: json_array <- list(a = 1, b = 2, c = list(d=3, e=4)) ) – renny Mar 05 '19 at 11:08
  • Thanks! That's one problem solved, but I would like "c" to available as a JSON array as mentioned at the end of the edit. – jerome Mar 05 '19 at 11:12
  • I think, you need to use JSONLITE too. – renny Mar 05 '19 at 11:22
  • I have updated the tags to include jsonlite. What would I need to do with jsonlite to get the format that I require? – jerome Mar 05 '19 at 11:27
-1

So the solution to this problem that I had to use was a JSON string in the body parameter. If for example, the following is the JSON string under consideration:

json <- {"a":1,"b":2,"c":[{"d":3,"e":4}]}

I had to pass this JSON string as the value for the "body" parameter for httr::POST() So the function call would look like:

r <- POST(url=url, body=json, encode="json", verbose())
jerome
  • 91
  • 7