Search code examples
rcurlrcurlhttr

Submitting an explicitly NULL parameter via httr


Is there a way to submit NULL as a JSON parameter via httr?

When I do httr::POST("https://httpbin.org/post", body = list(a = 1, b = NULL), httr::verbose(), encode = "json”), I see in the output that b = NULL gets dropped from the payload somewhere, even though list(a = 1, b = NULL) is a valid R list that has an existent b value set to NULL.

In Python's requests library, submitting a None parameter is permitted and I'm using an API that depends on that behavior (maybe not the smartest design choice, but it's what I have to live with). Is there any way for httr or RCurl or something to interface with this?


Solution

  • It seems that this is caused by body <- compact(body) in httr:::body_config. You could workaround by not providing the body as a list, but as character with the json directly.

    Not sure if the below returns exactly what you expect, but you could send the body directly as a character vector containing the json:

    httr::POST(
      "https://httpbin.org/post",
      body = '{"a":1,"b":"None"}',
      httr::verbose(),
      encode = "json"
    )
    

    Or, "programatically":

    httr::POST(
      "https://httpbin.org/post",
      body = jsonlite::toJSON(list(a = 1, b = "None"), auto_unbox = TRUE),
      httr::verbose(),
      encode = "json"
    )
    

    From httr:POST's help on the body parameter: https://www.rdocumentation.org/packages/httr/versions/1.4.0/topics/POST

    Note that with jsonlite::toJSON there are a few options to choose from, depending on what you actually want to POST as the body:

    jsonlite::toJSON(list(a = 1, b = NA), auto_unbox = TRUE)
    # {"a":1,"b":null} 
    
    jsonlite::toJSON(list(a = 1, b = NULL), auto_unbox = TRUE)
    # {"a":1,"b":{}} 
    
    jsonlite::toJSON(list(a = 1, b = NA_integer_), auto_unbox = TRUE)
    # {"a":1,"b":"NA"}
    
    jsonlite::toJSON(list(a = 1, b = list()), auto_unbox = TRUE)
    # {"a":1,"b":[]}