MSON Array Object "undefined" Error in API Blueprint - apiblueprint

We are developing a new API using HAL+JSON, leveraging Apiary.io's API Blueprint. We have been using JSON in our responses within the Blueprint itself. I'm testing a shift to using MSON instead, but am having an issue with an array object.
Here is the API Blueprint code. Everything works great, except for the curies array (toward the bottom), which contains one object.
FORMAT: 1A
# Content API
An API for retrieving content from NBC News Group.
# Group Root resource
The starting point for the Content API.
## Root Resource [/]
### Request root resource [GET]
+ Response 200 (application/hal+json)
+ Attributes (required, object)
+ _links (object) - Linked resources in HAL
+ self (required, object) - Self link to current document
+ href: / (required, string) - URI of this resource
+ profile: `http://domain.com/docs/profiles/root` (required, string) - URI to profile description for this resource
+ `nbng:content` (object) - Link relation to all content
+ href: `http://apiary-mock.com/content` (required, string) - URI to content
+ title: Browse all NBC News Group content (required, string) - title of the link relation
+ `nbcng:publishers` (object) - Link relation to all publishers
+ href: `http://apiary-mock.com/publishers` (required, string) - URI to publishers
+ title: Browse all NBC News Group publishers (required, string) - title of the link relation
+ `nbcng:publisher` (object) - Link relation to an individual publisher
+ href: `http://apiary-mock.com/publisher/{id}` (required, string) - URI to an individual publisher, with `{id}` query string param
+ templated: true (required, boolean) - Notes if the link has a URI template associated to it
+ title: Get a publisher by name (required, string) - title of the link relation
+ curies (required, array) - Link relation to documentation
+ (object)
+ href: `http://www.domain.com/docs/relation/nbcng/{rel}` (required, string) - URI to documentation
+ name: nbcng (required, string) - prefix of the link relation documentation is tied to
+ title: NBC News Group Link Relation (required, string) - title of the link relation
+ templated: true (required, boolean) - Notes if the link has a URI template associated to it
+ welcome: Welcome to the NBC News Group Content API (required, string) - Welcome message for resource
For that curies array, the API Blueprint output in JSON returns:
"curies": [
{
"undefined": null
}
]
When what is expected would be JSON that looks like this:
"curies": [
{
"href": "http://www.nbcnewsdigitaldev.com/docs/relation/nbcng/{rel}",
"name": "nbcng",
"title": "NBC News Group Link Relation",
"templated": true
}
]
Insofar as I can tell from the MSON specification, the syntax for the curies array and object are correct.
Would love any feedback from folks who've been on a similar MSON exploration.

I've run into a fair share of strange behavior with API Blueprint, MSON, and nested structures. In this case, you would assume what you did would work, or maybe specifying it as
+ curies (required, array) - Link relation to documentation
+ Attributes (object)
+ href: `http://www.domain.com/docs/relation/nbcng/{rel}` (required, string) - URI to documentation
+ name: nbcng (required, string) - prefix of the link relation documentation is tied to
+ title: NBC News Group Link Relation (required, string) - title of the link relation
+ templated: true (required, boolean) - Notes if the link has a URI template associated to it
That was still broken for me. But if you use Data Structures that seems to get it to render properly
FORMAT: 1A
# Content API
An API for retrieving content from NBC News Group.
# Group Root resource
The starting point for the Content API.
## Root Resource [/]
### Request root resource [GET]
+ Response 200 (application/hal+json)
+ Attributes (required, object)
+ _links (object) - Linked resources in HAL
+ self (required, object) - Self link to current document
+ href: / (required, string) - URI of this resource
+ profile: `http://domain.com/docs/profiles/root` (required, string) - URI to profile description for this resource
+ `nbng:content` (object) - Link relation to all content
+ href: `http://apiary-mock.com/content` (required, string) - URI to content
+ title: Browse all NBC News Group content (required, string) - title of the link relation
+ `nbcng:publishers` (object) - Link relation to all publishers
+ href: `http://apiary-mock.com/publishers` (required, string) - URI to publishers
+ title: Browse all NBC News Group publishers (required, string) - title of the link relation
+ `nbcng:publisher` (object) - Link relation to an individual publisher
+ href: `http://apiary-mock.com/publisher/{id}` (required, string) - URI to an individual publisher, with `{id}` query string param
+ templated: true (required, boolean) - Notes if the link has a URI template associated to it
+ title: Get a publisher by name (required, string) - title of the link relation
+ curies (required, array) - Link relation to documentation
+ Attributes (Cury)
+ welcome: Welcome to the NBC News Group Content API (required, string) - Welcome message for resource
# Data Structures
## Cury (object)
+ href: `http://www.domain.com/docs/relation/nbcng/{rel}` (required, string) - URI to documentation
+ name: nbcng (required, string) - prefix of the link relation documentation is tied to
+ title: NBC News Group Link Relation (required, string) - title of the link relation
+ templated: true (required, boolean) - Notes if the link has a URI template associated to it
Which rendered the endpoint with a response of
{
"_links": {
"self": {
"href": "/",
"profile": "http://domain.com/docs/profiles/root"
},
"nbng:content": {
"href": "http://apiary-mock.com/content",
"title": "Browse all NBC News Group content"
},
"nbcng:publishers": {
"href": "http://apiary-mock.com/publishers",
"title": "Browse all NBC News Group publishers"
},
"nbcng:publisher": {
"href": "http://apiary-mock.com/publisher/{id}",
"templated": true,
"title": "Get a publisher by name"
},
"curies": [
{
"href": "http://www.domain.com/docs/relation/nbcng/{rel}",
"name": "nbcng",
"title": "NBC News Group Link Relation",
"templated": true
}
]
},
"welcome": "Welcome to the NBC News Group Content API"
}

Related

Using graphql playground to test Saleor productCreate, what's the correct syntax for adding a product description?

In the code example below, if I exclude the description field the product is created successfully. With the description field in place I get a GraphQL error.
The code:
productCreate(
input: {
category: "Q2F0ZWdvcnk6MQ==", # Category ID
name: "Delete Me!", # Product name
productType: "UHJvZHVjdFR5cGU6MQ==", # Product Type ID
chargeTaxes: true,
weight: "0.3", # in Kg
rating: 5,
description: {text:"some text"}, # nope
}
)
The error:
graphql.error.base.GraphQLError: Argument \"input\" has invalid value {category: \"Q2F0ZWdvcnk6MQ==\", name: \"Delete Me!\", productType: \"UHJvZHVjdFR5cGU6MQ==\", chargeTaxes: true, weight: \"0.3\", rating: 5, description: {text: \"some text\"}}.",
"In field \"description\": Expected type \"JSONString\", found {text: \"some text\"}."
It is a string, for rich text it is using https://editorjs.io/
You can inspect the network tab in the dashboard to learn how APIs are being used
JSON string means providing a JSON text converted to a string. This can be achieved by escaping quotation marks within the JSON.
For example, this JSON
{ "text": "some text" }
can be converted to String as below:
"{\"text\":\"sometext\"}"
As you notice that the text encapsulated inside quotation marks, to be a valid String.
You can use https://jsontostring.com/ for the conversion
Your final code should be like this:
mutation {
productCreate(
input: {
category: "Q2F0ZWdvcnk6MQ==" # Category ID
name: "Delete Me!" # Product name
productType: "UHJvZHVjdFR5cGU6MQ==" # Product Type ID
chargeTaxes: true
weight: "0.3" # in Kg
rating: 5
description: "{\"text\":\"sometext\"}" # nope
}
){
product{
id
}
}
}
Sorting out the description syntax wasn't straightforward. From my question here:
Saleor on Github
I got this answer:
{
"id": "UHJvZHVjdDo3Mg==",
"description": "{\"blocks\":[{\"type\":\"paragraph\",\"data\":{\"text\":\"New description\"}}]}"
}
which I then implemented like this:
query = gql(
"""
mutation (
$slug: String!,
$product_title: String!,
$description: JSONString!,
$weight_grams: WeightScalar!,
)
{
productCreate(
input:{
category: "Q2F0ZWdvcnk6NQ==",
name: $product_title,
productType: "UHJvZHVjdFR5cGU6MQ==",
slug: $slug,
description: $description,
weight: $weight_grams,
}
)
{
errors {
field
message
}
product {
id
name
productType {
id
}
slug
}
}
}
"""
)
params = {
"product_title": str(product_title),
"description": '{"blocks":[{"type":"paragraph","data":{"text":"'
+ str(product_title + " (" + csv_product_id + ")")
+ '"}}]}',
"slug": str(csv_sku_code),
"weight_grams": str(weight_grams),
}
result = client.execute(query, variable_values=params)
This works well for us.

Prisma graphql computed fields

I have this datamodel:
type Item {
id: ID! #unique
title: String!
description: String!
user: User!
pictures: [Picture]
basePrice: Int!
addons: [Addon]
}
I'm writing a query called parsedItem that takes the id from arguments and looks for the Item (using the default query for Item generated by Prisma), something like this:
const where = { id: args.id };
const item = await ctx.db.query.item({ where },
`{
id
title
...
I need to show on the frontend a computed value: "dynamicPrice" it depends on the quantity of the Addons that the Item has.
e.g:
Item #1 has 3 addons, each addons has a value of $5. This calculated value should be
dynamicPrice = basePrice + 3 * 5
The Addon relation could change, so I need to compute this in every request the frontend makes.
I'd like so much to do something like:
item.dynamicPrice = item.basePrice + (item.addons.length * 5)
and return this item in the resolver, but this doesn't work. That throw an error:
"message": "Cannot query field \"dynamicPrice\" on type \"Item\"."
(when I try to query the Item from the frontend)
This error message makes me think: Should I create dynamicPrice as a field on the datamodel? Can I then populate this field in the query resolver? I know I can, but is this a good approach?
This is an example, I need to create more computed values for this Item model.
What is the best scalable solution/workaround for this simple use case?
You need create field resolver for dynamicPrice field at Item type. It will looks like that:
const resolvers = {
Query: {
parsedItem: (parent, args, ctx, info) => {
...
}
...
},
Item: {
dynamicPrice: parent => parent.basePrice + parent.addons.length * 5
}
}
More details you can find at A Guide to Common Resolver Patterns.

MSON to describe object attributes in blueprint

I have an issue similar to what is described here.
I have a JSON that looks like this:
{
"photos": [
{
"key": "y37dmj10jkwof/moOIUB8912JKVgh",
"caption": "A world of gamers.",
"tags": [
"game",
"japan"
],
"attributes": {
"copyright": true,
"use": [
"public",
"private"
]
}
}
]
}
and I am trying to describe the attributes using MSON, to render the blueprint. However, I am not successful at it. Here is my attempt:
+ Attributes (required, object)
+ photos (required, array)
+ (object)
+ key (required, string) - Photo key
+ caption (required, string) - Photo caption
+ tags (required, array)
+ game (string)
+ japan (string)
+ attributes (required, object)
+ (object)
+ copyright: true (required, boolean)
+ uses (required, array)
+ public (string)
+ private (string)
Ideas anyone?
Any input would be highly appreciated.
Here's an example that I think does what you want:
+ Attributes
+ photos (required, array)
+ (object)
+ key: y37dmj10jkwof/moOIUB8912JKVgh (required) - Photo key
+ caption: A world of gamers (required) - Photo caption
+ tags: game, japan (required, array)
+ attributes (required)
+ copyright: true (required, boolean)
+ use: public, private (required, array)
Note that you can put the sample values for the arrays as a comma separated list, and there's usually no need to explicitly state when the type is a string or object (unless it has no name). As for the attributes object, you can put the keys on it directly, no need to make another level with + (object)
Hope this helps!

multiple responses for a given endpoint in api blueprint

Is it possible in the API Blueprint to define a set of possible responses for a given endpoint?
For example if I have a endpoint such as /movie/{id} I'd like to be able to define a set of movie records so that in the mock server I could GET /movie/1 or GET /movie/2 or GET /movie/3 and get the relevant record.
The examples I've seen all seem to define just one possible response.
You can add multiple request blocks, like this:
### Register [POST]
Registers an account
+ Request Already existing username
+ Body
{
"app": 3,
"username": "already-existing-username",
"password": "password"
}
+ Response 200 (application/json)
+ Body
{
"success": false,
"error": "The username specified is already registered to an account.",
"error_field": "username"
}
+ Request Invalid password
+ Body
{
"app": 3,
"username": "username",
"password": "password"
}
+ Response 200 (application/json)
+ Body
{
"success": false,
"error": "Please supply a valid password.",
"error_field": "password"
}
You can also find this in the official documentation
It's not possible to simulate this using a single action, but there is a workaround.
FORMAT: 1A
# Multi
## GET /movie/1
+ Response 200 (application/json)
{ "id": 1, "title": "First" }
## GET /movie/2
+ Response 200 (application/json)
{ "id": 2, "title": "Second" }
## GET /movie/3
+ Response 200 (application/json)
{ "id": 3, "title": "Third" }
## GET /movie/{id}
+ Parameters
+ id (required, number, `42`) ... Blah.
+ Response 200 (application/json)
{ "id": 42, "title": "First" }
Now, if you hit /movie/2, the mock server sends the appropriate response. Thanks.
this is how you provide multiple responses in your RAML file using Mulesoft(API designer) however if you're using mocking service for testing you'll always get the example response you set for testing
/{id}:
get:
headers:
Requester-Id:
required: true
responses:
200:
body:
application/json:
type: Account
example:
!include exapmle/AccountExample.raml
400:
body:
application/json:
example:
{"message":"Error retrieving account for the provided id"}

Mapping relationships where the JSON representation can hold either a nested object or an object ID (in RestKit)

Is it possible to get RestKit to properly map relationships where the property might contain either a nested object or an object ID?
The API I'm currently working with often returns deep cyclical object graphs where multiple occurrences of the same object are replaced with the object's ID.
A simple example:
Nested
[
{
id: 1,
title: "Post Title",
category: {
id: 1,
name: "Category Title"
}
},
{
id: 2,
title: "Post Title",
category: 1
}
]
Since the replacement can happen at any level manually fixing the JSON before mapping is not very practical.

Resources