Embedded Assets
zdne opened this issue · 13 comments
Example use cases:
GET /users/1
{"name":"Bob", "email":"bob@example.com"}
GET /posts/1
{"title": "Hello World", "author":/* user 1 */}
GET /users/
[
/* user 1*/,
/* user 2*/
]
It would be nice if forward-references were supported too, so documentation for listing all models could appear above documentation to get a specific model.
If possible I would love to have opaque assets. By that I mean an asset (a pice of data e.g. a JSON file) that is opaque to the API Blueprint (and its parser). The main reason is that by violating this rule we would need to introduce a media-type specific escaping of asset references.
However to address this issue I was thinking about two possible, not necessary related, ways:
-
Provide a parser-harness that will be used generate data dictionaries (#9) to be referenced (#19) later in within a blueprint file
Basically a script that pre-generates media-type specific data dictionary files and its assets can be later represented like so:
[asset.one][] [asset.many][] [asset.ten][]
-
Utilize media-type agnostic parametric model message-body description (#28)
E.g.:
# User [/users/{id}] + Model + name (required, string, `Bob`) + email (optional, string, `bob@example.com`) # Posts [/posts/{id}] + Model + title (required, string, `Hello World`) + author (optional, [User][]) # Users Collection [/users] + Model + [User.many][]
This issue should be fully addressed in proposed Resource Blueprint Embedded Entities – Also #13
I have recently put a lot of thoughts into this. And I believe it might be beneficial to allow reference expansion on the asset level.
The main premise remains: An asset must remain opaque to API Blueprint parser (parser does not interpret what is inside), unless the blueprint author specifically does instruct the parser otherwise.
Embedded Entities
On-demand Asset Expansion Proposal
A payload body's content can include a reference to a resource (model) that is expanded by the parser if and only if the body definition is preceded by the embed
section specifying the respective symbol to expand.
For example:
# User [/users/{id}]
+ Model
{"name": "Bob", "email": "bob@example.com"}
# Users [/users]
+ Model
+ Embed: [User][]
+ Body
[[User][]]
# Blog Post [/posts/{id}]
+ Model
+ Embed: [User][]
+ Body
{"title": "Hello World", "author": [User][] }
This should improve current situation on modeling resources that embed other resources and also to increase DRY-ness of blueprints.
Thoughts?
This looks great! At the moment my only concern is that sometimes resources embed "mini" versions of other resources. By the looks of it only one model can be defined per resource. How might one use this approach to embed a mini-version of a resource without defining a new resource?
@BRMatt This is valid point Matt!
I am afraid that this can be achieved only by
- Writing the partial version anyway
- Using the MSON syntax to point which fields are included...
I still need to ponder this idea..
Looks really good, what are the plans for assets?
I have decided to not the collection "auto generation" of this feature at the moment
e.g.
[asset.one][]
[asset.many][]
[asset.ten][]
Without it, this issue should be addressed with the introduction of MSON in the API Blueprint as discussed here.
I'm going back and forth a bit in the documentation, examples, this issue and severak other issues in this repo, but I still can't figure out how to reference an array of JSON data in my API definition.
Can someone provide a clear example, with or without MSON, using Model or Attributes or Data Structures or whichever, as long as I can define one model somewhere, and then reference it for the body of a response, either for a targeted GET (single model) or collection GET (array of models)?
Thanks!
@adambuczynski You can find an example at https://apiblueprint.org/documentation/advanced-tutorial.html#data-structures. Where you can reference the data structure as follows for a single request/response:
+ Request (application/json)
+ Attributes (Question)
+ Response 200 (application/json)
+ Attributes (Question)
A collection of Question:
+ Response 200 (application/json)
+ Attributes (array[Question])
@kylef thanks, I've seen those docs/tutorials, but that's when using data structures.
As far as I understand, I need to define these data structures at the top of my api spec which is not very comfortable. Also, I thought I read somewhere that data structures are supposed to be limited to common chunks of data, not entire models.
With the Models, I can define them for a specific endpoint, and then reuse them in the response body, but only a single Model. Can I reference a collection of models somehow?
I think I've figured it out now, I just define the data structure under Attributes of the named endpoint, and then I can use the named endpoint as a reference in attributes for the response, e.g.:
## Item [/item]
+ Attributes
+ name: `Some item` (string)
+ date: `2015-08-05T08:40:51.620Z` (string)
### View item [GET /item/{itemId}]
+ Parameters
+ itemId (ObjectId, required)
+ Response 200 (application/json)
+ Attributes (Item)
### List items [GET /item]
+ Response 200 (application/json)
+ Attributes (array[Item])
This is what I was after, not very clear form the documentation and examples, as most examples include JSON in the response body and/or use Model for referencing data.