Facebook: field expansion in batch requests -> - facebook

How can I define the requested fields for the 2nd part of my batch request?
Example:
[
{
"method": "GET",
"name": "get-friends",
"relative_url": "me/friends?limit=5",
"omit_response_on_success": false
},
{
"method": "GET",
"relative_url": "?ids={result=get-friends:$.data.*.id}"
}
]
This works so far. But now I want to define the requested fields for the 2nd part.
When I add &fields=address ("relative_url": "?ids={result=get-friends:$.data.*.id}&fields=address") I get a "Batch parameter must be a JSON array" exception :-(
Ralph

I get a "Batch parameter must be a JSON array" exception
That probably just means your query could not be understood, because you invalidated the syntax somehow. & has a special meaning in a URL, so you most likely just need to encode it properly.
URL-encode the whole value of the batch parameter (so basically your whole JSON string that you got from your object.)
(What function/method to use for that, depends on how you build your request, resp. in what language. PHP has urlencode, JavaScript has encodeURIComponent, etc.)

Related

Should the resource ID be put in URL of PUT and PATCH requests?

Should PUT's and PATCH's URL contains ID or could it be put inside the body?
PUT /person/UUID {"name": "Jimmy"}
OR
PUT /person/{"UUID":1, "name": "Jimmy"}
( the same for the PATCH)
?
As PUT is defined as Replace the current document found at the URI location with the one provided in the payload sending a PUT request to /person should probably lead to a removal of any person managed by that particular endpoint, in case that URI represents a collection of persons.
As mentioned in this post one might use a URI without some special entity identifier in case this is an all purpose container. Think of a clipboard where you can copy some data to to later on retrieve it to paste it somewhere else. In such a case the identifier is implicitly given by the URI itself, as after all URI stands for unique resource identifier
Note that a URI as a whole identifies a resource and does not necessarily imply some form of parent-child structure. A client especially should not attempt to extract knowledge from an URI at all.
In regards to PATCH it depends. Usually one should use a media-type that is intended for patching such as JSON Patch or JSON Merge Patch.
The former representation defines certain fields that state that a field should be added, removed or replaced with a given value in a notation like the one listed below:
PATCH /my/data HTTP/1.1
Host: example.org
Content-Length: 326
Content-Type: application/json-patch+json
If-Match: "abc123"
[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]
JSON Merge Patch however works differently. It defines some default rules that instruct a server on how to apply the changes to the target document. A document like below i.e. will either add or update field a to have value z afterwards while the property f of c's object has to be deleted. All the other remaining properties of that resource remain as they are.
PATCH /target HTTP/1.1
Host: example.org
Content-Type: application/merge-patch+json
{
"a":"z",
"c": {
"f": null
}
}
Both of these media-types could be used to send a request directly to the "collection"-resource as both can target sub-elements by definition. However, in terms of caching I'd try to avoid it.
Caching in HTTP works de facto on the URI of the resource. Any unsafe operation performed on that URI leads to the cache invalidating a stored representation for that target. I.e. if you previously invoked GET /person/1 and now perform a PUT or PATCH, which both are unsafe operations, on /person the data might get updated, though a client requesting GET /person/1 afterwards may still retrieve the cached response via the cache as it is unaware of any changes done to that resource.

How do I avoid duplicate fields in Json request payload ? I'm using Apache Camel with REST

I wanted to parse json request by identifying duplicate fields in the request body. E.g. Assume I have below request.
`"employee": {
"name": "abc",
"name": "xyz",
"id": "6754",
"title": "supervisor",
}`
The employee request above has duplicate name field. ideally during json validation/parsing the second duplicate field takes precedence over first but I want to invalidate this kind of json request. How do I achieve this in Camel REST. Below is the approach that I tried but nothing worked. In myorg.apache.camel.builder.RouteBuilder, I tried configuring DataFormatProperty to use DeserializationFeature FAIL_ON_READING_DUP_TREE_KEY but its not failing. How do I fail the request for invalid json request which has duplicate fields.?
`#Override
public void configure() throws Exception {
restConfiguration().bindingMode(RestBindingMode.json).component("servlet")
.jsonDataFormat(JsonParser.Feature.STRICT_DUPLICATE_DETECTION.name())
.dataFormatProperty("prettyPrint", "true")
.dataFormatProperty("json.in.enableFeatures",
"FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS,FAIL_ON_READING_DUP_TREE_KEY"
+ ",FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE,"
+ JsonParser.Feature.STRICT_DUPLICATE_DETECTION.name())
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_EMPTY_BEANS").enableCORS(true)`
This may come from the fact that Camel is using XStream as default JSON library (see here).
Did you already try to force the use of Jackson library ?

IBM Cloud Function OpenWhisk node.js calling WIOTP over http

I am trying to use https://github.com/ibm-watson-iot/openwhisk-package-watsoniotp in an OpenWhisk sequence (containing two actions) all code is node.js
Testing the sequence using Postman. Once the action completes, the action returns the variable, payload. The variable payload is passed over to the next action in the sequence which is the openwhisk-package-watsoniotp (added via a binding in the IBM Cloud console so I am unable to modify this code, it is locked).
I can post data from postman into Watson IoT platform via the sequence. However the format of the payload is interpreted as a String, not a JSON string.
This is the body I post from Postman, one of the variants I have tried.
{"payload": "{'speed': 10}"}
My node.JS actions return the input, unmodified.
return {payload: params.payload};
The value should be a JSON string. However WIOTP is unable to interpret the payload and basically tokenizes the values. This is evident when I try to create a board and a card. The property list lets me select each value in the array.
enter image description here
The openwhisk-package-watsontiotp code as far as I can tell just takes, params.payload as is and passes it along.
I found an example in the code that answer the question,
The payload, should be nested. I missed that originally.
{
"key": "sampleInput",
"value": {
"eventType": "status",
"payload": {
"temp": 4
},
"domain": "messaging.internetofthings.ibmcloud.com",
"typeId": "xxxx",
"deviceId": "xxxx01"
}
}

Best practice for passing large parameter data to a REST call

I have a REST Service that allows user to pass in a list of Properties they want returned from the call, eg:
/Item/123/Properties/Name,Id,Description,Type
There are hundreds of Property names that can be passed in, which then causes the issue that the number of chars supported between segments (eg: /IamASegment/) is 260 without changes to the registry etc.
So my question is when I need to support the user passing in large amounts of data like this, what is the best method, should it be passed in via the header?
A proper REST solution would be to create a form on the previous page/state and submit that form via POST, which in turn would generate a redirected GET to the actual parameterized resource. The parameter in this case could be some number for example that represents a bit-field for the requested fields.
Something like this:
GET /items
{"form": {
"Id": { "type": "number" },
"Name" : { "type": "checkbox" },
"Description" : { "type": "checkbox" },
...
}
POST /items
{"Name": "true", "Description": "true", ... }
Redirects to:
GET /items/123?fields=110110111
Of course you would have to define the proper media-types for the forms, requests, responses, etc.

Can't add likes to the fields param

According to the Facebook Graph API documentation, the fields param acts as a result mask:
By default, most object properties are returned when you make a query.
You can choose the fields (or connections) you want returned with the
"fields" query parameter.
Indeed, this works fine for most fields. For instance, /7354446700?fields=name,picture returns:
{
"name": "Grooveshark",
"id": "7354446700",
"type": "page",
"picture": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-snc4/203560_7354446700_6819703_q.jpg"
}
However, for some reason, as soon as the likes field is added to the fields list, things break down. For instance, /7354446700?fields=name,picture,likes returns:
{
"name": "Grooveshark",
"id": "7354446700",
"type": "page",
"picture": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-snc4/203560_7354446700_6819703_q.jpg",
"likes": {
"data": [
]
}
}
Even more strange, if I omit the other two fields (name and pictures), sending only likes, I get
{
"likes": {
"data": [
]
}
}
The reason I find this extra-strange is because the "mandatory" fields (id and type) which should be added to every response are not included here (although they were included when fields=name,picture,likes).
What appears to be happening is that the field=likes parameter appears to be misinterpreted as a Connections request rather than simply a field mask, hence the data segment that normally appears when you'd call /7354446700/likes.
Is there a good reason for this? Is there any other way to get the likes field without fetching the entire object? I can't imagine this would be expected behavior, so I assume it is a bug, but I thought I'd ask here first before filing one.
This indeed appears to be a bug; I've checked internally and there's an as yet unresolved task open to fix this issue which was reported to us in our bug tracker previously.
In the meantime, the default return value for a page will include the 'likes' field even if it cant be retrieved solely.