How to pass parameter to REST API? - r

I am using R and have one question on how to pass parameter to the REST API REQUEST.
I already got the token and I am using R, and need to retrieve data from REST API service, by passing some parameters. Here is my code:
library(httr)
r <- POST("https://XXXXXXXX/api/locationhazardInfo",
add_headers("Content-Type"="text/plain; charset=UTF-8",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)),
body = list(
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
)
)
The tok is the token I got from previous step. And I got the systax errors (seem all syntax errors) as shown below,
Any input is greatly appreciated.
here is the screenshot of the error

Your body isn't a list. (I don't think!). I also think you have a rogue ) at the end (second last) which should be a }
A list would look like:
body = list(x = "A simple text string", y="Another String")
Your body is JSON encoded text.
body = '{"a":1,"b":{}}', encode = "raw")
So your code might look like this:
library(httr)
r <- POST(
"https://XXXXXXXX/api/locationhazardInfo",
add_headers(
"Content-Type"="text/plain; charset=UTF-8",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)
),
body = '{
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
}',
encode = "raw" )

An update, here is the solution at least it fixed my problem:
rg <- POST(url,
# add_headers("Content-Type"="text/plain; charset=UTF-8",
add_headers("Content-Type"="application/json",
Accept="text/plain",
"Authorization"=paste("Bearer", tok)),
body = '{
"Latitude":40.738269,
"Longitude":-74.02826,
"CountryCode":"USA",
"HazardLayers":[
{
"LayerId":"18",
"Description":""
},
{
"LayerId":"6",
"Description":""
}
],
"Distances":[
{
"Value":1,
"Unit":"miles"
}
]
}' ,
encode = "raw" #### , verbose()
)

Related

Writing data to google sheets using Google Sheets API with R

I try to write a data frame to google sheets using R. I've successfully added data frame example from google for developers API reference method selector but got Error 404 when tried to do so from my R script.
I've successfully got API credentials by token <- gargle::token_fetch() with spreadsheet and drive scopes. I've inserted some blank lines in the beginning of my table:
sheet_ins_range <- jsonlite::fromJSON('{
"requests": [
{
"insertRange": {
"range": {
"startRowIndex": 2,
"endRowIndex": 2,
"sheetId": XXXXX
},
"shiftDimension": "ROWS"
}
}
]
}')
sheet_ins_range$requests$insertRange$range$endRowIndex <- 10
body <- jsonlite::toJSON(sheet_ins_range)
response <- POST("https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}:batchUpdate",
body = body, encode = "json", config(token = token))
# response: Status: 200
But when I try to write some data into this region I get Error Status: 404.
google_BU <- jsonlite::fromJSON('{
"data": [
{
"range": "Sheet1!A1:D4",
"values": [
["Item", "Cost", "Stocked", "Ship Date"],
["Wheel", "$20.50", "4", "3/1/2016"],
["Door", "$15", "2", "3/15/2016"],
["Engine", "$100", "1", "3/20/2016"]],
"majorDimension": "ROWS"
}
],
"valueInputOption": "USER_ENTERED"
}')
body <- jsonlite::toJSON(google_BU)
response <- POST("https://docs.google.com/spreadsheets/d/{spreadsheetId}/values:batchUpdate",
body = body, encode = "json", config(token = token))
# response: Status: 404
I suppose I do something wrong with HTTP request, because there is nothing wrong with this request body when I use googles "Try this method" page.

Problem combining rawToChar() and write_json()

I have a problem with rawToChar() and write_json() where my result is a .json file that includes \n and \ and cannot be viewed in a "pretty" manner using notebook+. In addition I can't unfold or Uncollapse the result.
My working sequence is:
request <- httr::GET(
url = "https://myurl",
httr::content_type("application/json")
)
existing_distribution.json = jsonlite::prettify(rawToChar(request$content))
write_json(existing_distribution.json, "distribution.json"), pretty = TRUE)
When I open distribution.json with notepad+ I get a single line ...
["{\n \"ConfigurationStatus\": \"NOT_DEFINED\",\n \"economicStatus ... blahblah \n}\n"]
Any ideas?
Let there be a file example.json mocking your API containing
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
This is how to read the file as a raw sequence of bytes, parses it and saves it as prettified json:
library(jsonlite)
library(readr)
read_file_raw("example.json") %>%
rawToChar() %>%
parse_json() %>%
write_json("out.json", pretty = TRUE)
Resulting in file out.json containing:
{
"glossary": {
"title": ["example glossary"],
"GlossDiv": {
"title": ["S"],
"GlossList": {
"GlossEntry": {
"ID": ["SGML"],
"SortAs": ["SGML"],
"GlossTerm": ["Standard Generalized Markup Language"],
"Acronym": ["SGML"],
"Abbrev": ["ISO 8879:1986"],
"GlossDef": {
"para": ["A meta-markup language, used to create markup languages such as DocBook."],
"GlossSeeAlso": [
["GML"],
["XML"]
]
},
"GlossSee": ["markup"]
}
}
}
}
}

Translate curl call using httr in R, with multiple calls

I am trying to "translate" the curl call below, so that I can make an API call with R (using httr), with no luck. I have tried curlconverter and using the suggestion here. However, the API I want to access has multiple layers, and parenthesis are all over the place, which complicate conversion. Any suggestions for a function that will translate this recurring logic dynamically?
curl call:
curl -X POST 'https://api.notion.com/v1/databases/897e5a76ae524b489fdfe71f5945d1af' \
-H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
-H 'Notion-Version: 2021-05-13' \
-H "Content-Type: application/json" \
--data '{
"filter": {
"or": [
{
"property": "In stock",
"checkbox": {
"equals": true
}
},
{
"property": "Cost of next trip",
"number": {
"greater_than_or_equal_to": 2
}
}
]
},
"sorts": [
{
"property": "Last ordered",
"direction": "ascending"
}
]
}'
Desired outcome (function)
api_call(page, token, filters)
This question is a bit difficult to answer, since you have the access key and therefore nobody can test code to make sure it works. However, in terms of simply translating the curl call to httr code, I think the following code will do so.
library(httr)
library(jsonlite)
# Create the body of the POST request
json_body <- list(
"filter" = list(
"or" = list(
list(
"property" = "In stock",
"checkbox" = list(
"equals" = "true"
)
),
list(
"property" = "Cost of next trip",
"number" = list(
"greater_than_or_equal_to" = 2
)
)
)
),
"sorts" = list(
list(
"property" = "Last ordered",
"direction" = "ascending"
)
)
)
# Make post request
request <- POST(
url = "https://api.notion.com/v1/databases/897e5a76ae524b489fdfe71f5945d1af",
add_headers("Authorization" = paste("Bearer", notion_api_key),
"Notion-Version" = "2021-05-13"),
body = json_body,
encode = "json"
)
In terms of defining a function that creates the body dynamically, that's simply a question of formatting the filters similarly to the above example.

How to use only matchers at the stubs without applying body?

I am confused about behavior of body and bodyMatchers sections.
For example for a contract response.
I want my consumer (stub) to have a body from file (exact response from the stub) and producer only to have some matchers for the response (to validate reponse).
1 case I tried:
...
body (
file('__files/someFile.json')
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Expected - result:
Test has matchers for the reponse - false
Test doesn't have body matching - false
Stub has response body from the file - true
Stub doesn't have matchers - true
My workaround for a json body and response section:to add something for the producer body or i won't get matchers at the test response:
body (
$(
consumer(
file('__files/someFile.json')
),
producer(
cards: [
cardType: anyNonEmptyString()
]
)
)
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Shortly the problem I see - bodyMatchers requires body, but it is not intuitive. Response could have only matchers for the producer (tests) and request could have only matchers for the consumer (stubs).
I think it should work like this:
body (
$(
consumer(
file('__files/someFile.json')
)
)
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Updated:
request {
body(
file('__files/offer13-request.xml').asString()
)
bodyMatchers {
xPath('/a/b/c/text()', byRegex('123'))
}
}
And i see at the stubs:
{
"matchesXPath" : {
"expression" : "/soap:Envelope/#xmlns:soap",
"equalTo" : "http://schemas.xmlsoap.org/soap/envelope/"
}
}, {
"matchesXPath" : {
"expression" : "/a/b/c/text()",
"matches" : "123"
}
}
But i need only my matcher "expression" : "/a/b/c/text()"
I want my consumer (stub) to have a body from file (exact response from the stub) and producer only to have some matchers for the response (to validate reponse).
That's not how it works.
body (
file('__files/someFile.json')
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Means that
1) you have a body in a file someFile.json
2) it will be parsed and each part of the body will be analyzed like described in the json file
3) for th concrete json path there will be a regex verification (only for that json path)
Shortly the problem I see - bodyMatchers requires body, but it is not intuitive.
Since it's a bodyMatcher it requires a body. It kind of makes sense since it's a body matcher. If it was a matcher for headers it would require headers.

Mustache JS Template with JSON Collection

Hi this is my first attempt to use MustacheJS with a JSON webservice in .net
Currently I am struggling I can't seem to find what I am doing wrong setting this basic example:
My Webservice is returing the following string:
[
{
"ShortDescription":"BOX",
"Description":"BOXING",
"Id":1
},
{
"ShortDescription":"EPL",
"Description":"ENGLISH PREMIER LEAGUE",
"Id":2
}
]
I have validated its syntax with this website: http://json.parser.online.fr/
and here is the HTML code I am using:
google.load("jquery", "1");
google.setOnLoadCallback(function () {
$(document).ready(
function () {
$.ajax({
url: "../data.asmx/geteagues",
type: "POST",
dataType: "json",
data: "",
contentType: "application/json; charset=utf-8",
success: function (data) {
var template = "<h1>{{ShortDescription}} {{Description}}</h1>";
var html = Mustache.render(template, data);
$('#sampleArea').html(html);
alert(html);
}
})
}
)
});
I am posting the whole JS code, since I am not very good with javascript, basically I want to load always the latest JQuery version from google and then work my WS call.
The problem so far is that when I place a breakpoint in the following line:
var html = Mustache.render(template, data);
I see that the template is setn ok, and so does the data, same value as I posted above, but the .render function is returning: I seems It didnt like the data.
So far all the examples I have seen for inline data come as the following structure:
{
"repo": [
{ "name": "resque" },
{ "name": "hub" },
{ "name": "rip" },
]
}
And then a template defined like this:
{{#repo}}
<b>{{name}}</b>
{{/repo}}
But the only difference of that against my data is that I dont have a "parent" like "repo"
At server side, I am using a .net library called JSON.net and in the documentation of how are collections being serialized:
james.newtonking.com/projects/json/help/html/SerializingCollections.htm
the final result does not include the parent node's name, which I thing is missing from my Mustache Template definition:
[
{
"Name": "Product 1",
"ExpiryDate": "2000-12-29T00:00Z",
"Price": 99.95,
"Sizes": null
},
{
"Name": "Product 2",
"ExpiryDate": "2009-07-31T00:00Z",
"Price": 12.50,
"Sizes": null
}
]
Is this what I am missing? the "repo" parent node from my data so I can iterate my Template?
Thanks in advance for your time.
-ed
Per #stealth on this question Mustache.js: Iterate over a list received via json
{{ #. }}
<b>{{Name}}</b>
{{ /. }}
Note the only difference from #stealth's answer is a "#" instead of "/".
The line data = { 'roles': data }; is the most crucial. Its attaching the key to the data returned by web api or any other source of data like pagemethods or web service
$.ajax({
dataType: "json",
url: '/api/TestApi/GetAllRole',
success: function (data) {
data = { 'roles': data }; // formatting the data to support the mustache format
var html = Mustache.to_html($('#RoleTemplate').html(), data);
$('#tblRole').append(html);
}
});
Few of my articles on the MustacheJs can be found here
INLINE FILTER FOR BASIC GRID USING MUSTACHEJS
http://www.techguides.in/add-inline-filter-to-basic-grid-using-mustache/
Master Details Grid on Demand data loading : Using Mustache.JS
http://www.techguides.in/master-details-grid-on-demand-data-loading-using-mustache-js/
Sorting a Grid using MustacheJs
http://www.techguides.in/enable-sorting-in-a-grid-bound-using-mustache-js/
short answer: YES
long answer: for security reasons [1], you need to wrap your JSON aray in an object anyways. for Mustache or any other library to be able to access your array you need to have at least one parent key on which you can base your iterator.
The "repo" key on your sample is the helper you need to tell mustache "go and iterate on the array that is inside the repo key", otherwise you have no way to tell the template what you want to output where
[1] this is just one of many resources you can find about why you need to wrap your JSON response in an object http://incompleteness.me/blog/2007/03/05/json-is-not-as-safe-as-people-think-it-is/

Resources