How to pass a very long array of objects within a query string? - rest

There is a RESTful API with some resource. I need to GET some resource with parameter which in JSON representation looks like:
{
"id": int,
"params":
[
{
"param1": "string",
"param2": "string"
},
{
"param1": "string",
"param2": "string"
}
]
}
I have two possible ways to send this object in the query string:
id=1&params[0].param1=test&params[0].param2=test&params[1].param1=test&params[1].param2=test
id=10000&params[0][param1]=test&params[0][param2]=test&params[1][param1]=test&params[1][param2]=test
The problem is that params array can have a lot of items and the query string can be very long, over 2,000 characters.
To send params in the request body via GET is bad idea.
How I can send such params in a proper RESTful way? Can I use other HTTP method? Or just change the query length on the server?

Use a POST method to get some data because params are too long for a GET method ISN'T a bad idea.
You can add the search options in body of request in JSON like
{
"id": int,
"params":
[
{
"param1": "string",
"param2": "string"
},
{
"param1": "string",
"param2": "string"
}
]
}

If you want an idempotent request URI (i.e. response is always the same), then use GET, else POST.
For more details you can find here for answers:- Why should I POST data rather than GET?

Related

Response tag with URL parameter

Is there any way in an Insomnia request to use the response body of a sub-request in the request body, and at the same time specify a URL parameter for that sub-request?
Consider an API with endpoints like these:
[GET] _.base_url/customers/{id}
[GET] _.base_url/products/{id}
[POST] _.base_url/invoices
When POSTing to the invoices endpoint, the API expects a JSON body along these lines (highly simplified, of course):
{
"date": "2022-03-31",
"currency": "USD",
"customer": {
"id": 123,
"name": "Something Corp.",
"address": "Here, there and everywhere"
},
"items": [
{
"id": 456,
"description": "Thingamajig",
"price": 11500
},
{
"id": 789,
"description": "Doodad",
"price": 23900
}
]
}
That is, it expects the customer field and each of the items fields to be full objects, not just IDs. (And yes, that’s stupid and not RESTful, but I don’t control the API.)
The proper way to retrieve such objects would obviously be to call the two GET endpoints with the IDs as part of the URL, and then using the responses as response tags in the POST request – but I cannot find a way to do this.
There’s a lengthy GitHub discussion on per-request veriables which has so far not produced any results, but even the suggested PR in that thread doesn’t seem like it would support defining the URL parameters when calling the request, rather than in the request itself.
Is there some way to achieve this in Insomnia?

Infobip API. How to create list of list of objects by api

I would like to create custom attribute list of list of objects in Infobip by API.
I have try to sent POST but in doesn't work.
Can you give me please the example of POST request to create the list of the list.
Thx!
Off Doc: https://www.infobip.com/docs/api#customer-engagement/people/create-a-custom-attribute
Request examples:
1.{
"name": "payrollData",
"dataType": "LIST_OF_OBJECTS",
"objectSchema": {
"DATE": "DATE",
"Transactions": "LIST_OF_OBJECTS"
}
}
2.{
"name": "payrollData",
"dataType": "LIST_OF_OBJECTS",
"objectSchema": {
"DATE": "DATE",
"Transactions":{
"Input": "DECIMAL",
"Output": "DECIMAL"
}
}
}
Responses:
1.{
"errorCode": 40001,
"errorMessage": "Bad Request",
"validationErrors": [
{
"code": 501,
"message": "Custom attribute schema is invalid.",
"propertyPath": "valueSchema"
}
]
}
2.{
"requestError": {
"serviceException": {
"messageId": "BAD_REQUEST",
"text": "Bad request"
}
}
}
At this point is not possible to achieve what you are trying via using Infobip API.
The functionality for creating custom attributes is limited only to top layer and does not support nesting of the list objects.
The team in charge will include that explanation in API docs description. But, there are no plans on including additional complexity layers on this endpoint in the short future.
So generally, you can use LIST_OF_OBJECTS as described on the endpoint URL you also linked to. But you are not able to layer it furthermore.
Valid example for LIST_OF_OBJECTS usage:
{
"name": "ShoppingCartList",
"dataType": "LIST_OF_OBJECTS",
"objectSchema": {
"productName": "STRING",
"productPrice": "DECIMAL",
"productCategory": "STRING",
"productImage": "STRING"
}
}
I know it does not resolve your issue as you would have hoped for, but it is a correct answer. :)

Using Cloud Firestore REST API how to send data using http package with http.post() method

I have a collection called "txt" and would like to create a new document under that, with an auto-generated document Id, with the field 'test' and its value as 'title'.
I have the following code in Flutter which does not work:
Future<http.Response> _post() {
String url =
'https://firestore.googleapis.com/v1/projects/onebear-webapp/databases/(default)/documents/txt?key=AIzxSyAllNuEbN40DEvBPIQkcLIWn00c9TYWqY';
return http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'test': 'title',
}),
);
}
And it keeps giving errors as per below:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"test\" at 'document': Cannot find field.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "document",
"description": "Invalid JSON payload received. Unknown name \"test\" at 'document': Cannot find field."
}
]
}
]
}
}
I cant seem to figure out the error message and what the errors "Invalid JSON payload received." or "fieldViolations" mean - even though I'm encoding with jsonEncode.
Please any help or guidance on this very much appreciated. Thx!
I would suggest you have a look at these similar posts (1)(2) with other users running into similar issues.
If you want to update multiple fields and values, have you managed to try to specify each one separately? For example, your request body should look something like this:
{
"fields": {
"field": {
"stringValue": "Value1"
},
"Field2": {
"stringValue": "Value2"
}
}
}
Since it seems you are attempting to set up a string Hash. I would suggest you have a look at this documentation on map's field as it follows a different structure, for example: An object containing a list of "key": value pairs.
map (key: string, value: object (Value))
{ "name": "wrench", "mass": "1.3kg", "count": "3" }
Since jsonEncode looks to be a functionality specific to Flutter development, I would recommend bringing your question to the Flutter developers team as the they would be more knowledgeable of this implementation method.

Should links in json-api responses be encoded?

Should the query params in links appearing in JSON-API responses be percent-encoded?
The examples from jsonapi.org are not encoded, as in:
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page[offset]=2",
"last": "http://example.com/articles?page[offset]=10"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
}
]
}
However, there is also a note regarding encoding parameters in requests:
GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
Accept: application/vnd.api+json
Note: The above example URI shows unencoded [ and ] characters simply for readability. In practice, these characters must be percent-encoded, per the requirements in RFC 3986.
Does this note apply only to requests? Or should responses also be percent-encoded, as in:
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page%5Boffset%5D=2",
"last": "http://example.com/articles?page%5Boffset%5D=10"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
}
]
}
Yes, the note about encoding URI's in your question applies only to the request, not the response
With a json string returned inside a response, the only thing required to escape is the double quote character "
GET requests (not responses) are a different ball of wax. Anything in a GET request passed as a parameter in the URL must be URL encoded. So if you have a parameter url=http://some.url.com, the url on the right of the parameter assignment needs encoding.
It's tricky with POST and PUT requests. Depending on the content type set in the header you may need to encode. If your content type is application/json, you should not need to url encode anyting in your json string, (excluding the before mentioned ").
Now, if the specificed content encoding you state doesn't match what your sending (or if you didn't explicitly add one and it defaults to something), like if you send content-type: application/x-www-form-urlencoded but send a json string, the API service may or may not accept it and who know what how it will treat the content inside as far a url decoding it.

Getting specific headers along with other body data in Users.thread: get

You can very easily select what headers you want in a Users.thread: get-request, like so:
format = metadata
metadataHeaders = From
GET https://www.googleapis.com/gmail/v1/users/me/threads/14eaffaf5e3e8242?metadataHeaders=From&format=metadata&key={YOUR_API_KEY}
Response:
{
"id": "14eaffaf5e3e8242",
"historyId": "510358",
"messages": [
{
"id": "14eaffaf5e3e8242",
"threadId": "14eaffaf5e3e8242",
"labelIds": [
"SENT",
"INBOX",
"IMPORTANT"
],
"snippet": "Wow Emil!",
"historyId": "510292",
"internalDate": "1437471536000",
"payload": {
"mimeType": "multipart/mixed",
"headers": [
{
"name": "From", // I just got the header I asked for.
"value": "Emil Tholin <emtholin#gmail.com>"
}
]
},
"sizeEstimate": 9260
}, ...
}
You can also get certain parts of the body very easily. E.g. here I ask for the attachmentIds of all the attachments in the message body:
field = messages/id,messages/payload/parts/body/attachmentId
GET https://www.googleapis.com/gmail/v1/users/me/threads/14eaffaf5e3e8242?fields=messages%2Fid%2Cmessages%2Fpayload%2Fparts%2Fbody%2FattachmentId&key={YOUR_API_KEY}
Response:
{
"messages": [
{
"id": "14eaffaf5e3e8242",
"payload": {
"parts": [
{
"body": { // This message had an attachment.
"attachmentId": "ANGjdJ_0lphTo48BO0xBT_YOSo3tYah23hzpjyATe3GwfziK0I6401P_8-ZYoGuCQPHhpPP0-S_pjL68WIEZzQ0tu72RcIOE4UY3kA4u8PjXPf3Cm5PxVJjmH9N0hm0fFX31RYo8bfZQ6l7bDbYbnCSZbckG7g8enGaKMPbBzIEEC4HXr_YghOYWSfrXKXiFLnxWN4LfsFk3IXUN2tVvMe_0xMhDDfBlqYPnXHr2PhPghq7bQojNxiH4YziIqaKmwiU4xqVfygbae-K-_Q2blyz0EgI4OXjMzwz56Q5e1w"
}
}
]
}
},
{
"id": "14eaffb277b61cd0" // This message had no attachment.
}, ...
]
}
As you can see in the first request, no part of the body is retrieved when asking for specific metadata headers. Individual fields are also hard to pick out in the fields-parameter, since headers are not key-value pairs, but objects on the form { "name": <HEADER_NAME>, "value": <HEADER_VALUE> }.
Is there any way to combine these two requests? I would like to get all the relevant metadata about a message at the same time as getting how many attachments there are in the message.
From Users.threads.get.
"metadata": Returns email headers with message metadata such as identifiers and labels.
The fields parameter is only used to limit the amount of data returned. Since metadata mode is already a limited response you can't use fields to get data outside of that subset. Your best option would be to use your second example with fields and then filter the metadata values locally.