Ember Data JSON-API hasMany: How? - ember-data

I'm familiar with the old ember-data "sideloading" model, which would look like this:
```
{
authors:[
{id:1, name:"Ernest", type: 'author', books: [1,2]
],
books: [
{id:1, name: "For whom the bell tolls", type: 'book', author:1},
{id:2, name: "Farewell To Arms", type: 'book', author:1}
]
}
But the new JSON-API method is different.
For one thing, (and I like this), attributes are separated from the id and type information, preventing namespace collisions.
I don't yet understand how to do a hasMany relationship with the JSON-API format. Can anyone point me to a doc or article on how this is expected? The examples on the JSON-API page show individual relationships, but not hasMany.
If you could write the above example in the new format, you'd have answered my question.

I found the answer in The JSON-API spec.
Each model should have a relationships key, whose value is an object with a key for each named relationship, which also has a data key that can be either a single object or an array for a hasMany relationship.
By providing an included key as top-level member, I can lazy load the entities.
In this case, the above example would be:
{
"data": [
{
"id": 1,
"type": "author",
"attributes": {
"name": "Ernest"
},
"relationships": {
"books": {
"data": [
{
"id": "1",
"type": "book"
},
{
"id": "2",
"type": "book"
}
]
}
}
}
],
"included": [
{
"id": 1,
"type": "book",
"attributes": {
"name": "For Whom the Bell Tolls"
},
"relationships": {
"author": {
"data": {
"id": 1,
"type": "author"
}
}
}
},
{
"id": 2,
"type": "book",
"attributes": {
"name": "Farewell to Arms"
},
"relationships": {
"author": {
"data": {
"id": 1,
"type": "author"
}
}
}
}
]
}

FYI: If you want to fetch a hashMany relationship at a later time, you have two other options.
1. Use a Related Resource Link:
As soon as the hashMany relationship is needed, Ember Data will call the backend with related link to fetch all the relations.
{
"data": [{
...,
"relationships": {
"books": {
"links" {
"related": "http://example.com/books"
}
}
}
}]
}
2. Use find-ids
As soon as the hashMany relationship is needed, Ember Data will call the backend with an url to fetch given ids. In this example it would be http://example.com/books?ids=1&ids=2
{
"data": [{
...,
"relationships": {
"books": {
"books": {
"data" [{
"id": "1",
"type": "book"
}, {
"id": "2",
"type": "book"
}]
}
}
}
}]
}

Related

How to add new or existing multi-select tags when creating a page in Notion API?

I can't figure out how to add multi-select tags when creating a page in Notion API. Single select tags are extremely easy to add:
"City": {
"select": {
"name": "New York",
}
}
But my attempts to add multi-select tags end up failing.
"City": {
"multi_select": {
"options": [
{
"name": "New York",
"color": "red"
},
{
"name": "Tbilisi",
"color": "gray"
}
]},
}
Here's the error I get
{"object":"error","status":400,"code":"validation_error","message":"body failed validation. Fix one:\nbody.properties.City.title should be defined, instead was `undefined`.\nbody.properties.City.rich_text should be defined, instead was `undefined`.\nbody.properties.City.number should be defined, instead was `undefined`.\nbody.properties.City.url should be defined, instead was `undefined`.\nbody.properties.City.select should be defined, instead was `undefined`.\nbody.properties.City.multi_select should be an array, instead was `{\"options\":[{\"name\":\"apple\",\"color\":\"red\"},{\"name\":\"Ora...`.\nbody.properties.City.people should be defined, instead was `undefined`.\nbody.properties.City.email should be defined, instead was `undefined`.\nbody.properties.City.phone_number should be defined, instead was `undefined`.\nbody.properties.City.date should be defined, instead was `undefined`.\nbody.properties.City.checkbox should be defined, instead was `undefined`.\nbody.properties.City.relation should be defined, instead was `undefined`.\nbody.properties.City.files should be defined, instead was `undefined`.\nbody.properties.City.status should be defined, instead was `undefined`.\nbody.properties.Name.id should be defined, instead was `undefined`.\nbody.properties.Name.name should be defined, instead was `undefined`.\nbody.properties.Name.start should be defined, instead was `undefined`."}
Do you have a working example of how it should be done?
Here's the full payload
newPageData = {
"parent": { "database_id": 'some id' },
"properties": {
"Name": {
"title": [
{
"text": {
"content": "New page"
}
}
]
},
"City": {
"multi_select": {
"options": [
{
"name": "New York",
"color": "red"
},
{
"name": "Tbilisi",
"color": "gray"
}
]},
},
"Date": {
"date": {
"start": "2023-02-06",
"end": None,
}
},
"Link": {
"url": "example.info"
}
}
}
When populating / updating a Multi-Select property, you don't need to include "options" or specify the option's colour so this should work -
"City": {
"multi_select": [
{
"name": "New York"
},
{
"name": "Tbilisi"
}
]
}
you should remove the first comma at the end of your list of options for the City property too -
]},
},

Certain relations are added to the product entity for no reason

I have been using OroCommerce's API for creating products through POST requests. The request works fine but I have one problem once the entity has been created. For some reason, OroCommerce will add extra relations to the product entity.
For example, if I create a product with the name "testt", the request will have the following data :
{
"data": {
"type": "products",
"attributes": {
...
},
"relationships": {
"data": [
{
"type": "productnames",
"id": "name"
}
]
}
},
"included": [
{
"type": "productnames",
"id": "name",
"attributes": {
"fallback": null,
"string": "testt"
},
"relationships": {
"localization": {
"data": null
}
}
},
...
]
}
But when I send the POST request, the resulting entity I get has 2 name relationships instead of one, here's what the data of the resulting entity looks like with a GET request and including names :
"included": [
{
"type": "productnames",
"id": "450",
"attributes": {
"string": null,
"fallback": "system"
},
"relationships": {
"product": {
"data": {
"type": "products",
"id": "445"
}
},
"localization": {
"data": {
"type": "localizations",
"id": "1"
}
}
}
},
{
"type": "productnames",
"id": "451",
"attributes": {
"string": "testt",
"fallback": null
},
"relationships": {
"product": {
"data": {
"type": "products",
"id": "445"
}
},
"localization": {
"data": null
}
}
},
...
]
As you can see, the resulting object has an extra name relationship, even though it was never in the initial POST request to start with. I have the same issue with descriptions, shortDescriptions, where a relation with empty data gets created even if I explicitly set the data to null in the POST request.
Is there a way to prevent this?
The case is that every localizable field MUST have a value for every localization and one by default.
Such entities as
productnames
productdescriptions
productshortdescriptions
localizedfallbackvalues
can contain either a string value or fallback link to the default value or some other localization.
As is seen from your examples you have only one localization so when you create a product with
{
"type": "productnames",
"id": "name",
"attributes": {
"fallback": null,
"string": "testt"
},
"relationships": {
"localization": {
"data": null
}
}
}
the system creates a "productnames" instance with a string value inside as a default value
{
"type": "productnames",
"id": "451",
"attributes": {
"string": "testt",
"fallback": null
},
"relationships": {
"product": {
"data": {
"type": "products",
"id": "445"
}
},
"localization": {
"data": null
}
}
}
and then automatically adds "productnames" instances for each localization with fallback links (in your case one instance)
{
"type": "productnames",
"id": "450",
"attributes": {
"string": null,
"fallback": "system"
},
"relationships": {
"product": {
"data": {
"type": "products",
"id": "445"
}
},
"localization": {
"data": {
"type": "localizations",
"id": "1"
}
}
}
}
An absence of localizable field default value in a POST body will trigger "Not Null constraint".
So as detailed above every localizable field MUST has a value (or fallback) for each localization. So every time a product or localization entity is created system adds a linking entity for every intersection of every localizable field and every localization.

Make a property required depending on a query parameter with OpenAPI and JSON-Schema

I have a REST API that support for most calls a with query parameter, allowing the user to specify which additional fields they want to load along with the resource’s basic data.
I can describe the query parameter with OpenAPI, and I can describe the format of the response with JSON-Schema. But how can I describe the relation between the parameter and the response?
What I want to describe is:
/api/resource/{id} returns:
{"id": 123, … }
/api/resource/{id}?with=stuff returns:
{"id": 123, …, "stuff": { … }}
I would like this stuff property to be defined as required. Is there a way of doing this?
(What makes this probably even more impossible is that the value of with can be a comma-separated list of properties, but at this point I’m not hoping)
You can't do anything in JSON Schema using out of context data. So, the only way to do what you want is to put the query data into your response.
{
"id": 123,
"query": {},
...
}
{
"id": 123,
"with": ["stuff"],
...
"stuff": { ... }
}
With pure JSON Schema or OpenAPI 3.1, you can use if/then and contains to express the conditional requirement.
{
"type": "object",
"properties": {
"id": { "type": "object" },
"with": { "type": "array", "items": { "type": "string" } },
...
"stuff": { ... }
},
"required": ["id"],
"allOf": [
{
"if": {
"properties": {
"with": { "contains": { "const": "stuff" } }
},
"required": ["with"]
},
"then": { "required": ["stuff"] }
},
... additional conditionals ...
]
}
However, assuming you are on OpenAPI 3.0, you don't have if, then, or contains. It's still possible, but it gets a bit ugly because you need to use a bunch of confusing boolean logic concepts instead.
{
"type": "object",
"properties": {
"id": { "type": "object" },
"with": { "type": "array", "items": { "type": "string" } },
...
"stuff": { ... }
},
"required": ["id"],
"allOf": [
{
"anyOf": [
{
"not": {
"properties": {
"with": {
"not": {
"items": { "not": { "enum": ["stuff"] } }
}
}
},
"required": ["with"]
}
},
{ "required": ["stuff"] }
]
},
... additional conditionals ...
]
}
JSON schema: query string required
schema: {
tags: ["sample"],
summary: "Set query string values to required",
querystring: {
type: "object",
properties: {
name: {
type: "string",
},
address: {
type: "string",
},
},
required: ["name"],
},
},

Backand - use own db row id as primary key

Is it possible to specify your own row ID in backand objects? I want to form one-to-one relationsships in database, where I have two objects: userPrivateData and userProfile
I would like to use the id of Backands own internal user object as primary key for both objects. So basically a userId. The reason for this: With REST api you can access single items with GET /1/objects/{name}/{id}
Since I don't know the row id I want to use another unique identiefier as primary key, that I know - my user id.
Is this possible? Maybe I have the concept all wrong, in their docs they talk a lot about one-to-many relationships and stuff, but not about one-to-one relationships.
I think your JSON model would look something like this.
[
{
"name": "items",
"fields": {
"name": {
"type": "string"
},
"description": {
"type": "text"
},
"user": {
"object": "users"
}
}
},
{
"name": "users",
"fields": {
"items": {
"collection": "items",
"via": "user"
},
"allofuserprivatedata": {
"collection": "userPrivateDataThings",
"via": "userId"
},
"email": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"userProfile": {
"object": "userProfile"
}
}
},
{
"name": "userProfile",
"fields": {
"userid": {
"collection": "users",
"via": "userProfile"
},
"fieldOne": {
"type": "string"
},
"fieldTwo": {
"type": "boolean"
}
}
},
{
"name": "userPrivateDataThings",
"fields": {
"field1": {
"type": "string"
},
"field2": {
"type": "float"
},
"userId": {
"object": "users"
}
}
}
]
Use a collection when you want 1 to many.
Use an object when you want 1 to 1.
When you do a GET on user with deep:true the nested relationship data will come back in the response.

Jira REST API: create issue linked to another one

I'd like to link an issue to an existing one at creation using the REST API. The idea is not to CREATE then UPDATE, but just CREATE.
Here is my JSON:
{
"issueUpdates": [
{
"fields": {
"project": {
"key": "CMDB"
},
"issuetype": {
"id": "10500"
},
"summary": "VMP-MYSQL-01",
"issuelinks": [
{
"type": {
"name": "Relates",
"inward": "relates to",
"outward": "relates to"
},
"inwardIssue": {
"key": "CMDB-825"
},
"outwardIssue": "CMDB-825"
}
],
"customfield_10600": "VMP-MYSQL-01"
}
}
]
}
The error I get is:
{
"issues": [],
"errors": [
{
"status": 400,
"elementErrors": {
"errorMessages": [],
"errors": {
"issuelinks": "Field does not support update 'issuelinks'"
}
},
"failedElementNumber": 0
}
]
}
Does the API support the creation of Linked Issue at creation? Using the GUI works.
Jira is running v6.2.
Since this question is a bit older, I've been experiencing same issue as you. After some searching I found that instead of fields you can use update in the json you send to server.
Alternatively, you can use issueLink method to add links after creating the issue.
Complete code to create an issue with a link to a different issue:
{
"fields": {
"summary": "Sample Issue",
"project": {
"id": 14505
},
"issuetype": {
"id": 11002
}
},
"update": {
"issuelinks": [
{
"add": {
"type": {
"name": "Relates"
},
"inwardIssue": {
"key": "PRJ-1"
}
}
}
]
}
}
This will solve your problem. This will create an issue with one jira issue linked to it.
key is a project key,
Blocks or related to whichever you want.
put below json into http://jsonlint.com/. It will do proper formatting.
{
"fields": {
"summary": "Test Adapter",
"project": {
"key": "WFM"
},
"description": "Testing of Jira from Adapter",
"issuetype": {
"name": "Bug"
},
"update": {
"issuelinks": [{
"add": {
"type": {
"name": "Blocks",
"inward": "is blocked by",
"outward": "blocks"
},
"outwardIssue": {
"key": "WFM-28",
"fields": {
"summary": "Test Adapter"
}
}
}
}]
}
}
}