I'm documenting a public API that has a method named /findGuild that takes a mandatory key parameter and one of the following parameters:
byPlayer
byName
It must have either byPlayer or byName; My question is: How do I indicate that byPlayer and byName are mutually exclusive, but one is mandatory?
Right now, I have the following in my .apib for this Resource:
### GET /findGuild{?byName,byPlayer,key}
+ Parameters
+ byName: `YourGuild` (string, optional) - Search for the Guild by its name.
+ byPlayer: (string, optional) - Search for Guild by a player. Does not seem to work.
+ key: `ffffffff-ffff-ffff-ffff-ffffffffffff` (string, required) - The user's API key.
+ Response 200 (application/json)
+ Attributes (object)
+ guild (string) - The guild id or null.
+ success (boolean) - Should be true.
+ Body
{
"guild": "ffffffffffffffffffffffff",
"success": true
}
I am afraid (but not totally sure) API Blueprint is not capable of expressing this kind of relationship at the moment.
What I can surely tell you is that, according to public roadmap, URI Parameters will be replaced with an MSON object, which supports the scenario you're asking for.
Hope it helps!
Related
What is the use of ! in !include and ? in get?: and <<>> and also resourceTypes?
I am not able to understand with examples provided either in the official website or some other websites?
Can some explain with a clear example?
There's no use for "!" alone, the keyword "!include" includes the "!". I think the reason is to allow the use of the "include" word as a resource or in other parts of a RAML spec, without colliding with this keyword.
"?" marks the property as optional, a "get?" declares that method as optional in a resource type. "For example, a resource type declaration describes a body parameter that is used if the API defines a post method for that resource. Applying the resource type to a resource without a post method does not create the post method."
"<<>>" Double angle brackets enclose a parameter name in resource type and trait definitions. For example:
resourceTypes:
rt:
get:
description: <<someParam>>
/foo:
type: { rt: { someParam: bar } }
That, will set a get method in resource "/foo", with the description "bar"
These can be used with any name, but there are 2 reserved keywords that are useful when defining resource types and traits, which are resourcePath and resourcePathName. resourcePath is the full resource URI relative to the baseUri if there is one. And resourcePathName is the rightmost of the non-URI-parameter-containing path fragments.
For example for a resource "/groups/{groupId}", resourcePath will be exactly that and resourcePathName will be "groups". See the example bellow on how to use this.
Resource and method declarations are frequently repetitive, a Resource Type is a way of avoiding this repetition. If you have the same pattern for a group of resources, then you define a resource type "foo" and then declare the type of those resources as "foo".
In this example there are several resources which have a get method that retrieves all records of a type, and a post method that adds one of more records of a type:
types:
books: !include types/books.raml
persons: !include types/users.raml
animals: !include types/animals.raml
resourceTypes:
collection:
get:
description: get all <<resourcePathName>>
responses:
200:
body:
application/json:
type: <<resourcePathName>>
post:
description: adds one or more <<resourcePathName>>
body:
application/json:
type: <<resourcePathName>>
/books:
type: collection
/persons:
type: collection
/animals:
type: collection
The key here is using <<resourcePathName>>, when on the /books resource, <<resourcePathName>> will return "books". And thus, will set the type of the get response and the type of the post request to books.
The same happens for the other 2 resources.
In my blueprint I'm defining a data structure and try to use it like so
+ Attributes
+ error: (Error Details, required)
Data structure definition at the end of the document:
# Data Structures
## Error Details
+ code : 1234 (number, required) - see list of error codes
+ message: User not found (string, required) - a human-readable error message
The resulting sample response body looks just like expected but the validation on apiary.io shows semantic issues for each of the places where I use constructs like this, saying "No value(s) specified".
Am I doing something wrong or is it a problem with the apiary.io parser?
I had the same problem and solved it by
omitting the colon
separating the object definition and type (see owner in this example):
Company (object)
name: Company name (string)
owner (OwnerResponse) (object)
A similar answer to other current answers, but none the less this fixed it for me.
No good:
+ Attributes
+ `status`: OK
+ `data`:
+ 5 (Channeldata)
+ 7 (Channeldata)
Fix:
+ Attributes
+ `status`: OK
+ `data`
+ 5 (Channeldata)
+ 7 (Channeldata)
As others have noted, losing a colon in the right place can fix things.
Attribute section can be also defined as + Attributes <Type Definition> (specification), so defining + Attributes (Error Details, required) should fix the given semantic issue.
Edit:
You have to omit a colon between attribute's name and its type, when an example value is not defined:
+ Attributes
+ error (Error Details, required)
Missed that before, sorry.
I have a REST api url endpoint that represents a Song within an Album:
/api/album/(?P<album_id>)/song/(?P<id>)/
and I want to refer to it from another resource, e.g. Chart that contains Top-1000 songs ever. Here's an implementation of ChartSerializer:
class ChartSerializer(HyperlinkedModelSerializer):
songs = HyperlinkedRelatedField(
queryset=Song.objects.all(),
view_name='api:song-detail',
lookup_field='id'
)
class Meta:
model = Chart
fields = ('songs', )
Clearly, I can pass id as lookup_field, but it seems to me that I won't be able to pass album_id by any means. I'm looking into HyperlinkedModelSerializer.get_url() method:
def get_url(self, obj, view_name, request, format):
"""
Given an object, return the URL that hyperlinks to the object.
May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
attributes are not configured to correctly match the URL conf.
"""
# Unsaved objects will not yet have a valid URL.
if hasattr(obj, 'pk') and obj.pk in (None, ''):
return None
lookup_value = getattr(obj, self.lookup_field)
kwargs = {self.lookup_url_kwarg: lookup_value}
return self.reverse(view_name, kwargs=kwargs, request=request, format=format)
As you can see, it constructs kwargs for reverse url lookup from scratch and doesn't allow to pass additional parameters to it. Am I right that this is not supported?
UPDATE:
Found a reference to this problem in the issue list of DRF: https://github.com/tomchristie/django-rest-framework/issues/3204
So, the answer is YES. There is even a paragraph about this issue in the DRF documentation:
http://www.django-rest-framework.org/api-guide/relations/#custom-hyperlinked-fields
Consider this excerpt from https://github.com/apiaryio/mson#example-1 ...
Example 1
A simple object structure and its associated JSON expression.
MSON
- id: 1
- name: A green door
- price: 12.50
- tags: home, green
Let's say I would like to define valid values for the name attribute. Consider a context of API testing with a tool such as Dredd. We may need to define what are the expected/valid name values in response to GET'ing this resource, or else something is probably broken and this test step should fail.
And/or, if creating/updating a resource of this type, we may need to define what name values are valid/accepted. Is this currently possible to define in MSON?
(I believe this can be done in a JSON schema, which makes me hopeful for MSON support.)
Following is an example API Blueprint resource to illustrate how this would be used...
# Thing ID [/api/thing/id]
# List Thing ID attributes [GET]
+ Response 200
+ Attributes
+ href (string)
+ make (string)
+ model (string)
+ version (string)
+ Body
{"href":"/api/thing/id","make":"BrandX","model":"SuperThingy","version":"10.1"}
In the above example, there are 3 known/accepted/valid values for the model attribute: CoolThingy, AwesomeThingy, and MLGThingy
Can we represent this resource in MSON, such that...
Apiary (or other rendered) API documentation consumers can easily know what model values to expect?
Dredd processes and passes/fails the model value in the response to a GET to this resource?
In MSON you can use enum, see the example below.
name (enum[string])
joe (default)
ben
mark
When writing an API-Deocumentation for an rest-service I came across an problem where I wanted to list all the possible Values which could be returned as a response.
In the case below it would be the "state" field which could contain any possible value of a enumeration and I wanted to sum up which possible states there are.
I could not find an easy and nice way to do it with apiblueprint. Is there a way to display sections collapsed by default and expand them when additional information is needed?
Here is the Sample code I have:
## Sample [/Sample?{id}]
Get all the information for the sample
+ Parameters
+ id = `0` (Integer, optional) ... The Id of the resource to get
+ Model (application/json)
+ Body
{
"name": "Name of the Resource",
"state": "deleted"
}
### Retrieve the sample data of the system [GET]
+ Response 200
[ProviderConfiguration][]
I need something like "Values" for the parameters section but for the Body part to describe the state in the Body section e.g.
<collapsible>
+ state (EnumType) ... current state of the sample object
+ Values
+ `active`
+ `inactive`
+ `deleted`
</collapsible>
Unfortunately, this is not yet possible with API Blueprint. However, it's planned - see https://github.com/apiaryio/api-blueprint/issues/25 and https://github.com/apiaryio/mson.