I'm developing a REST API based on the HAL specification. The API is being developed in PHP with Symfony and the client is being build in angularjs. The API must return some lists and they are going to be shown using ngtables library, and filtering options will be needed, ideally in the format that ngtables uses, like in this sample.
{ "name": "M", "age": "4" }
(Of course future clients may be use the same options.)
My frontend-workmate is suggesting me to send the json encoded directly as a parameter in the url, like this:
?filter=%7B%20%22name%22%3A%20%22M%22%2C%20%22age%22%3A%20%224%22%20%7D%20
I'm not very sure about that though.
I've been reading how to send arrays through the URL with a parameter like param[]=foo¶m[]=bar but that does implies have one key for multiple values. In my case I need to be able to send different key-values for the arrays like a Json object does.
I'm wondering how should be the Request URL from the client to be able to include all the filter options inside one parameteror and if there is any standard way to do that.
EDITED: After #Ross_Turner I want to clarify that my intention of passing a key-value array inside a parameter is because we'll have another type of parameter. For example:
?filter=<my key-value array>&page=1&limit=50&anotherParam=whatever
Even we would like to use another parameter containing another key-value array like this:
?filter=<my key-value array>&sorting=<another key-value array>&page=1&limit=50
Where filter and sorting can have the same keys.
Currently there is no standard way to send queries in GET requests. So you have 2 options: you use your custom query language (like you already tried) or you choose a standard query language. Either way it is hard to make it RESTful, because you have to create a link, which contains a recipe how to generate such an URI. You can probably use URI templates, but sometimes they are not general enough...
#Ross Turner:
I think you misunderstood, I was talking about not having a standard. Ofc. there are non standard query string based solutions, for example RQL. Or you can send a standard SPARQL query in a single param, but there is no standard way to describe such a link, and without link descriptions you cannot generate the query in a REST client, so it won't be loosely coupled and so it will violate the uniform interface constraint.
I disagree with #inf3ero's answer - surely there is a very well defined way to send a query as part of a GET request - query parameters. If you want different key and value combinations this is the principal of the keys and values of query parameters, so in your example you should probably use ?name=M&age=4 and parse each of these on your server. It should be simple enough to convert
{ "name": "M", "age": "4" }
into this by iterating over the keys in the JSON object. I'm not sure why you would want to combine these into a single parameter if you are attempting to implement a RESTful API following the HAL specification.
Related
I am parsing an XML document to JSON, and eventhough I have the type array declared in the json schema, if there is just one element in the array it gets transformed into an objet like this.
"ListOfCodes":{"Codes":{{"Code":"111"}}}
but I need this:
"ListOfCodes":{"Codes":[{"Code":"111"}]}
I have several arrays in the document and I only get the sqare brackets when there is a multiple array.
and adding the properties manually is not an option.
Anyone know what can i modify to fix this in the logic app?
Unfortunately, there isn't a good solution for us to implement this requirement in logic app. Here is another post which is similar to your problem. To implement the requirement, we can just:
1. Use the "Compose" action to generate the object by hand (manually put all the properties and arrays where they need, potentially using the #array() action.
2. Call an Azure Function or some external code that can more specifically craft a valid JSON.
I also try to test it in some other way, such as use json:Array="true" and use <?xml-multiple?> but they all fail in logic app. So I think the only above two solutions(mentioned in that post) can be used. Neither approach is good, though.
I have an LTI Tool Consumer(LMS) that is using LTI1p0 which will send a request to a service that is currently not using LTI. Therefore I'm writing a NodeJS implementation of a wrapper which will
receive from the LTI Tool Consumer,
map it to match service's API,
send it to the service,
then parse the response from the service into an LTI Tool Provider format,
and finally send it back to the Tool Consumer.
The service has a required field called groups which expects an array of group objects like so:
group: [ {
id: <string>, // id of the group
name: <string>, // name of the group
role: <string> // role of the user
}]
This parameter doesn't exactly exist in the LTI1p0 implementation guide. So I want to know how to best send array-type (groups in my case) information via LTI.
When looking through the docs, I've come across a few potential parameters I could use:
1. Context parameters
The guide mentions that a 'type of context would be "group"', and there are parameters for context_id, context_type, context_title. The issue would be that this is only an option for one group per request/user.
2. Custom parameters
I could make a custom parameter and call it custom_groups which seems simple, but I'm not sure how the value should look for arrays? Just like a stringified json object?
custom_groups = "{"id":123,"name":"Group Name","role":"Instructor"}, {"id":124,"name":"Group Name 2","role":"Creator"}"
For the roles parameter, one can send a list of comma-separated strings (i.e. roles= Instructor, Creator,..)but that wouldn't suffice in my case.
I'm still new to LTI, so my apologies if this is blatantly obvious.
Note: Both LTI Consumer (LMS) and the service are external, i.e. I can't change them and only provide the wrapper. I can communicate with the Tool Consumer about possible custom parameters but again not sure which format to request.
Additionally, the service might implement LTI towards the end of the year, so ideally the wrapper could then be removed and the Tool Consumer wouldn't have to change much.
Any help much appreciated!
Groups are notably absent from the LTI spec. So any answer will be part opinion.
I would agree with you that using the context parameter fields, with one LTI launch per group. Would be the most correct way, as far as the spec goes.
However I have not seen an LMS that allows LTI launches from group context. So you may not be able to use the service without a wrapper, even if it supported LTI natively.
Alternatively:
LTI 1.0 Supports custom parameters, as you are extending the the information already sent (context and roles) You could use the ext_ prefix.
Referer: https://www.imsglobal.org/specs/ltiv1p0/implementation-guide
If a profile wants to extend these fields, they should prefix all fields not described herein with "ext_".
So you could send a custom parameter with that prefix. Assuming your LMS lets you send a useful custom paramater. LTI is designed to use basic POST request, Not multidimensional Json objects. But a stringified JSON object is perfectly valid with an appropriate key.
i.e:
ext_custom_groups = "{"id":123,"name":"Group Name","role":"Instructor"}, {"id":124,"name":"Group Name 2","role":"Creator"}"
I am designing a web service accepting POST requests with JSON in the message body. I want the requestor to be able to specify multiple values for a parameter, but also single values.
So, for simple cases I support JSON like:
{
"name" : "value"
}
And, in more complex cases, I also support JSON like:
{
"name" : [
"value one",
"value two",
"value three"
]
}
My question is: is this an abnormal interface for a Web Service? Am I overcomplicating things here?
The alternative would be, as I want to support arrays of values, to require arrays of values, even for the simple case:
{
"name" : [
"value"
]
}
I don't like this but want to get the community's input before making a decision.
EDIT:
I removed the word REST from the conversation as that factor isn't really important here.
It is typical of a web service to accept an array of values for a POST request. However, the number of elements may be zero or many. Keeping it as an array of values, even if only one value is going in, is going to keep things simple and consistent.
If a user of the web service needs to submit a single element for creation or modification (upsert), then perhaps a PUT request would be more appropriate.
I will prefer a single structure for both cases and then there will be only one processing logic to code and no need for special case to decide on.
Also this is not much of REST related. It is more of on trading off on the the processing or handling of the data v.s. whatever reasons that drive you to think of splitting the data into two forms in the first place.
Hope this help.
REST is about resources and their representations. So ask yourself:
What resource does the JSON represent?
Can you answer this question?
From the JSON in your question I would say, the resource is an object that has names
. It is not an object that has one name.
So I recommend to use your second approach.
I'm trying to figure out how to get nested structs to work with GAE datastore using Go. I know the datastore doesn't specifically support nested structs. I need to find a simple way of getting user information to go with a post when it is sent out to a user as JSON.
One thing I thought of was to put two fields for the user. One for the ID/key referencing to user and another one for the user type struct which would be added there when the post is loaded from the datastore. Extra fields seem silly so I'm hoping there is a better solution for this.
There are two entity types or structs: POST and USER
Posts need to contain information about the user who made the post.
The structure for the JSON I'm going to output for users is as follows:
POST
field1
field2
USER
user_field1
user_Field2
Go's appengine datastore api provides the PropertyLoadSaver interface for this sort of thing: https://developers.google.com/appengine/docs/go/datastore/reference#PropertyLoadSaver
You structure your struct however you want and then implement the Load and Save methods of that interface to populate it correctly. It means you write the serialization code yourself but it gives you full freedom in how you structure your data.
This will allow you still filter over the fields and have a nested struct.
The python runtime has the ndb library which supports nested structures like this. Go does not, so I can think of two solutions:
In the POST kind, have a user field that is a key, referencing a USER kind with the necessary fields. Requires two fetches and roundtrips.
Make a user field in the POST kind that is a blob. The blob is a string that is [de]serialized in go. This means you can't search or filter on any of the user data, but it also allows you to store everything in one entity.
You should use these based on the needs of your app. If you need users to be a real thing, use 1. If users aren't objects you need to work with (i.e., just data to display), you can use 2.
I am trying to make a simple twitter client in C. I'm new at this and not sure how to go about segregating meaningful stuff from the JSON string that I get from the API.
For example, if I get this as a response from the API, how do I extract out the value of "text" into a string (char*)? I guess I can work with the string at low level, but wouldn't that become too tedious every time I need to get a value from the JSON string?
For JSON in general, json.org has a big list of parsers implemented in a ton of different languages.
For C:
JSON_checker
JSON parser
json-c
M's JSON parser
YAJL
cJSON
Jansson
jsmn
Why not just use one of the existing libraries for working w/ Twitter?
http://apiwiki.twitter.com/Libraries
As a more direct response to your question, I'd recommend not trying to do text parsing on your own, but instead have classes that mean something to your domain that you can then use the JSON serialization/deserialization logic that comes w/ the framework, e.g.
http://msdn.microsoft.com/en-us/library/bb412179.aspx
Hope that helps,
Paul