I am writing a mobile client that consumes JSON data from a 3rd party server (one which I have no control on). The problem is when I do a get on the following URL
curl http://server.com/zm/api/events.json
It returns a big list of events structured like so:
"events": [
{
"Event": {
"Id": "280",
"MonitorId": "1",
"Name": "Familyroom-280",
"Cause": "Motion",
"StartTime": "2015-04-12 06:54:43",
"EndTime": "2015-04-12 06:55:27",
"Width": "1280",
"Height": "960",
"Length": "44.24",
"Frames": "74",
"AlarmFrames": "23",
"TotScore": "973",
"AvgScore": "42",
"MaxScore": "279",
"Archived": "0",
"Videoed": "0",
"Uploaded": "0",
"Emailed": "0",
"Messaged": "0",
"Executed": "0",
"Notes": "Motion: mudroom door, study door"
}
}, //and many more such "Event" events inside the array
I'm new to JSON, but when I read up, its specification say the server MUST provide a mechanism to extract any sub object. So, for example, I want to construct a URL to ONLY retrieve events which have a MonitorId of 1
I've tried
curl http://server.com/zm/api/events/Event/MonitorId/1.json
curl http://server.com/zm/api/Event/MonitorId/1.json
curl http://server.com/zm/api/events.json?MonitorId="1"
curl http://server.com/zm/api/events.json?Event.MonitorId="1"
But I can't seem to get it right. Can someone advise what is the URL I need to construct to only return elements where MonitorId="1"?
thanks!
By REST you don't start to construct URLs. That's the responsibility of the server, if it does not provide hyperlinks with URLs (or URI templates), then we are not talking about REST.
Try a different response format, maybe there is HTML, ATOM, JSON-LD, HAL+JSON, etc... something which contains hyperlinks.
I thought this is like xpath and I can drill down to whatever level I
want.
Most of REST services do not support custom queries.
Take a look at ZoneMinder docs:
Return a list of events for a specific monitor Id
Example :
curl -XGET http://server.com/zm/api/events/index/MonitorId:1.json
Or you can just filter your JSON output with the jq command.
Example:
curl http://server.com/zm/api/events.json | jq '.events | map (.Event | select(.MonitorId==1))'
Related
I was thinking about the possibility of executing a specific http method (POST or PUT) in POSTMAN without specifying it.
I mean; imagine if there was a field in a JSON file called: METHOD within 2 possible states: 'I' corresponding to INSERT OR POST and the another one: 'U' related to UPDATE or PUT
Something like this: (please, do note the field called "method"):
[
{
"sku": "95LB645R34ER",
"method": 'I'
"payload": {
"price": "147000",
"tax_percentage": "US-21",
"store_code": "B2BUSD",
"markup_top": "1.62",
"status": "1",
"group_prices": [
{
"group": "CLASS A",
"price": "700038.79",
"website": "B2BUSD"
}
]
}
},
{
"sku": "95TYS34344ER",
"method": 'U'
"payload": {
"price": "69978",
"tax_percentage": "US-21",
"store_code": "B2BUSD",
"markup_top": "9.99",
"status": "1",
"group_prices": [
{
"group": "CLASS B",
"price": "88888.79",
"website": "B2BUSD"
}
]
}
}
]
I would like to run that JSON using the Collection Runner but i have no idea how to do the trick. I mean, everytime i generate a collection i have to specify the HTTP METHOD otherwise it wont know what to do.
I want the program to adjust that by looking at the JSON file, if "method":'I' then, perform a POST or if "method":'U' execute a PUT method. Do you get me?
I've been reading the documentation but i did not find something like that or maybe i did not understand. I'm not an expert on POSTMAN :(
Can you help me?
EDIT:
Alright, i did this:
In the request UI, use the {{METHOD}} syntax where you would see the HTTP method. This is an editable field as it allows you to add custom HTTP methods.
In the file, use the METHOD key and any HTTP verb as the value. Ensure that it's part of each object in the datafile as you will need it for each iteration.
I am designing a REST call that should deliver information for a location (lat/lon) and consider the user context/configuration.
As the number of user properties is high and nested, I am not sure, what is the correct way to design a new query (GET vs POST). Currently we use a POST request for simplicity - the query payload could look like this, but is custom and very different for each user. It also includes an array of multiple configuration items. Currently the request looks like this:
POST http://api.something.com/locationInformation
{
"location": {
"accuracy": 30,
"coordinates": [
16.34879820048809,
48.230067741347334
],
"provider": "network",
"timestamp": "2016-01-06T12:00:00.000Z"
},
"userConfiguration": [
{
"id": "asdfasdfasdfs09898sdf",
"values": [
"false"
]
},
{
"id": "iojkljio230909sdjklsdf",
"values": [
"99jkjiouio89",
"sdfilkjöjfoi093s09sdf"
]
}
]
}
So my question is: is it in such a case ok to "abuse" a POST request in order to query information?
Is there an elegant way to pass such data using a GET request?
Yes u can pass this data using a GET request by passing it to a request header.
use the header() method.Initialize a String variable say String data=//your json; and pass it to the header as follows header("data",data) in your client while building the request.
i'm making a new application using Parse.com as a backend, i'm trying to make less requests to the Parse, I have a class which is pointing to another object of another class.
Class1(things):
ObjectID Name Category(pointer)
JDFHSJFxv Apple QSGKqf343
Class2(Categories):
ObjectID Name Number Image
QSGKqf343 Fruits 45 http://myserver.com/fruits.jpeg
when i'm trying to retreive data for my first class things using REST API i'm getting this json object :
{
"results": [
{
"Name": "Apple",
"createdAt": "2015-07-12T02:50:20.291Z",
"objectId": "JDFHSJFxv",
"category": {
"__type": "Pointer",
"className": "Teams",
"objectId": "QSGKqf343"
},
"updatedAt": "2015-07-12T02:55:33.696Z"
}
]
}
the json doesn't contains all the data included in the object i'm pointing to, I will have to make another request to get all the data of that object,
is There any way to fix that
You need to tell Parse to return the related object in your query, via the include key.
e.g., add the following to your CURL --data-urlencode 'include=category'
I am designing a JSON API for a mobile app and have to decide how to show child objects from the server to the client. Typically the request from the client to the server will be a single request to sync and the response will include all the objects that need updating. What is the best way to show the objects?
Option A - Nested Children:
{ "articles": [
{ "id" : 1,
"title": "This is the first article",
"comments": [
{"id": "1",
"article_id" : "1",
"title": "A comment on the first article"
}]
},
{ "id" : 2,
"title": "This is the second article",
"comments": [
{"id": "2",
"article_id" : "2",
"title": "A comment on the second article"
}]
}, ]}
OPTION B - All Objects on Their Own
{ "articles": [
{ "id" : 1,
"title": "This is the first article",
}
{ "id" : 2,
"title": "This is the second article",
}]
"comments": [
{"id": "1",
"article_id" : "1",
"title": "A comment on the first article"
},
{"id": "2",
"article_id" : "2",
"title": "A comment on the second article"
}]}
On the client side I can handle either format and build the relationship based on the article_id field so I am not too sure why nest the children, other than that it makes it look nice. However, when I think about writing tests for the client-side, especially the mapping of json to objects it seems easier to show and map each object on its own. I am a beginner here so any thoughts would be helpful.
PS. I am building the server using Rails/Grape and the clients with RestKit/Coredata (iOS) and probably RoboSpice/ORMLite (Android).
That's very subjective. There isn't one correct answer for that. It really depends on whatever approach is more suited to your task and data. You say this is a request used to sync data. How is the data represented and stored on the client side? If flat, like a relational database, then the flat output is probably easier to use. On the other hand, if the client will use the relationships a lot, it's probably better to use the nested structure.
From an API design standpoint, I'd have the endpoint for the articles collection accept a query parameter like expand, with a level number, or named entities, and it would add the nested children accordingly. So, for instance, GET /api/articles?expand=comments would generate output with nested comments, or GET /api/articles?expand=1 to generate output with all immediate children. That way, clients can easily generate the nested output if they need it, or they can query the endpoints for articles and comments separately and concatenate the output if they need the flat data.,
What is the right way to format your responses in JSON and why? I've seen different services do it two ways, consider a simple GET /users resource:
{
"success": true,
"message": "User created successfully",
"data": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
That is how I usually do that. I have some abstract helper fields like success and message, there may be some more but the question is if should I nest the data in the data field to an array called the same way as the resource - users:
{
"success": true,
"message": "User created successfully",
"data": {
"users": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
}
Even if we don't use the abstraction:
{
"users": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
Seems the users key is obsolete as any client will know the route they called, which consists of /users, where users are mentioned, and the client code like
$users = $request->perform('http://this.api/users')->body()->json_decode();
looks much better than
$users = $request->perform('http://this.api/users')->body()->json_decode()->users;
as it avoids repeated users.
One use case where the envelope can be useful is when you are expecting to be dealing with large lists and need to do pagination to prevent huge response payloads. The envelope is a good place to put the pagination meta data:
{
"users": [...],
"offset": 0,
"limit": 50,
"total": 10000
}
(This is what we do in a RESTful API I'm working on)
Clearly this is only relevant for requests that return lists of things (e.g. /users/) and not for requests that return single entities (e.g. /users/42) and even for requests that return lists, you don't have to use an envelope - one alternative would be to use response headers for this meta data instead.
PS. I would only advise having a success and message fields if you have a concrete use case for them. Otherwise don't bother, they are simply unnecessary.
Just to get on the same page, data is a field in a JSON object. In the first example the value of data is an array. In the second example the value of data is an object.
Either is valid, so to answer your question: no it is not necessary to nest named objects in an named object. It is necessary that all fields of an object be named, but you are free to nest arrays within an object.
It really just depends on what the processor expects. If data can be anything, then the first approach is fine. If code expects the value of the data field to be an object, then you have to use something like the second example.
According to your comment which you added to first comment: more descriptive data is better data as every information is useful for consumer of you API - REST endpoint. So if you know that the content is user, or whatever, it's better to use it in schema or endpoint url.
Better description = better consuption :-)