jsonapi-serializer overwrites existing "links" attribute - node.js

I use an API that returns a response with the following structure:
{
"data": [
{
"id": "id-1",
"type": "objectType",
"attributes": { ... },
"links":
"linksDataAndMetadate": {...}
}, ...
],
"links":
"thisLink": "some url",
"thatLink": "another url"
}
We use jsonapi-serializer package in our code base for serialization/deseiralization, but when I use it to deserialize the response, the outer links part (the ones that includes "thisLink" and "thatLink") overwrites the "links" field inside the object attributes. Is there a way to use the package so that it will have a different behavior?

Related

AWS CDK Api Gateway Models Ref Dependency - Model reference must be in canonical form

I am trying to add multiple models in the same time using aws CDK when one of the models is referencing the other one.
Ex:
"Gender": {
"contentType": "application/json",
"modelName": "GenderModel",
"schema": {
"type": "string",
"enum": [
"Not Specified",
"Male",
"Female",
"Non-Binary"
],
"schema": "http://json-schema.org/draft-04/schema#",
"title": "GenderModel"
}
},
and
"Requirements": {
"contentType": "application/json",
"modelName": "RequirementsModel",
"schema": {
"type": "object",
"properties": {
"gender": {
"ref": "https://apigateway.amazonaws.com/restapis/${Token[TOKEN.791]}/models/GenderModel"
}
},
"required": [
"gender",
],
"additionalProperties": false,
"schema": "http://json-schema.org/draft-04/schema#",
"title": "RequirementsModel"
}
},
When i deploy this fails with
Model reference must be in canonical form
From what i can see this fails because the GenderModel does not exists. If i first add the GenderModel in the stack and then i add the RequirementsModel and deploy again it works just fine because the GenderModel was previously created. If i want to create both of the models in the same time it will fail.
I tried to make sure the order of addModel call is correct but it seems it does not work.
Solution Found
Seems like you have to add explicitly specify the dependency.
modelB.node.addDependency(modelA)
This will avoid the error and add the models in the correct order
The problem is https://apigateway.amazonaws.com/restapis/${Token[TOKEN.791]}/models/GenderModel, specifically the ${Token[TOKEN.791]} part. When the API is not created, at CloudFormation synthetisation time, id is not known and placeholder value used - https://docs.aws.amazon.com/cdk/latest/guide/tokens.html
You can use the Ref intristic function to compose model by the reference
const getModelRef = (api: RestApi, model: Model): string =>
Fn.join(
'',
['https://apigateway.amazonaws.com/restapis/',
api.restApiId,
'/models/',
model.modelId]);

Microsoft Graph Api upload file to SharePoint

I'm using microsoft graph api to interview with sharepoint.
Upload file to sharepoint.
https://graph.microsoft.com/v1.0/sites/abc78c05-a77b-45bf-a1a1-51f09548b497/drive/root:/test1212123.txt:/content
Then we can got the response.
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('abc78c05-a77b-45bf-a1a1-51f09548b497')/drive/root/$entity",
"#microsoft.graph.downloadUrl": "https://yeeofficesg.sharepoint.com/sites/GdTest/_layouts/15/download.aspx?UniqueId=b9d25e13-c915-432f-b9fb-f2d36a188d9f&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAveWVlb2ZmaWNlc2cuc2hhcmVwb2ludC5jb21AMzgzMDNhNTQtMjUwMS00MDcwLTlkYjItYzNmNTY2OTc2NGUxIiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTU4NDY4MjQ5OSIsImV4cCI6IjE1ODQ2ODYwOTkiLCJlbmRwb2ludHVybCI6InltcjVvWHhDU0FIaFhhV0tYVnZuVDVjK05ETnZsejhzcC9YeFp3MStQaHc9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxMzUiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6IlpUUmhPVFk1WkdFdE5EQXlOQzAwWlRnMExUazFZelF0WkRkalpqRmpOR1UxTm1ZMCIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJZV0pqTnpoak1EVXRZVGMzWWkwME5XSm1MV0V4WVRFdE5URm1NRGsxTkRoaU5EazMiLCJhcHBfZGlzcGxheW5hbWUiOiJIdHRwUmVxdWVzdCBUZXN0IiwibmFtZWlkIjoiNTk3ZDQ4YmMtMDVmMy00MTU4LThhY2MtYWU1Y2M3YTljNmFkQDM4MzAzYTU0LTI1MDEtNDA3MC05ZGIyLWMzZjU2Njk3NjRlMSIsInJvbGVzIjoiYWxsc2l0ZXMud3JpdGUgYWxsZmlsZXMud3JpdGUiLCJ0dCI6IjEiLCJ1c2VQZXJzaXN0ZW50Q29va2llIjpudWxsfQ.aTVxeDdWNkowcWFDK0xYOHUvZGo3K0VVSEd1dU02MFVheEFJbnBWWUJHTT0&ApiVersion=2.0",
"createdDateTime": "2020-03-20T05:34:59Z",
"eTag": "\"{B9D25E13-C915-432F-B9FB-F2D36A188D9F},1\"",
"id": "016REKDTITL3JLSFOJF5B3T67S2NVBRDM7",
"lastModifiedDateTime": "2020-03-20T05:34:59Z",
"name": "test1212123.txt",
"webUrl": "https://yeeofficesg.sharepoint.com/sites/GdTest/Shared%20Documents/test1212123.txt",
"cTag": "\"c:{B9D25E13-C915-432F-B9FB-F2D36A188D9F},1\"",
"size": 12,
"createdBy": {
"application": {
"id": "597d48bc-05f3-4158-8acc-ae5cc7a9c6ad",
"displayName": "HttpRequest Test"
}
},
"lastModifiedBy": {
"application": {
"id": "597d48bc-05f3-4158-8acc-ae5cc7a9c6ad",
"displayName": "HttpRequest Test"
}
},
"parentReference": {
"driveId": "b!BYzHq3unv0WhoVHwlUi0l_EO2rYM2NNCptmOTvJ-EqeM9aeJ-zj_TZktSrctfA1S",
"driveType": "documentLibrary",
"id": "016REKDTN6Y2GOVW7725BZO354PWSELRRZ",
"path": "/drive/root:"
},
"file": {
"mimeType": "text/plain",
"hashes": {
"quickXorHash": "RBBCDGQwAxrUIARAFAEJSgAAAAA="
}
},
"fileSystemInfo": {
"createdDateTime": "2020-03-20T05:34:59Z",
"lastModifiedDateTime": "2020-03-20T05:34:59Z"
}
}
Then I want to update the customized column of this list.
https://graph.microsoft.com/v1.0/sites/abc78c05-a77b-45bf-a1a1-51f09548b497/lists/89a7f58c-38fb-4dff-992d-4ab72d7c0d52/items/80/fields
step3, I needs the item id (this example is : 80)
but when I upload the file, I can't got the item id directly from the response.
use this api:https://graph.microsoft.com/v1.0/sites/abc78c05-a77b-45bf-a1a1-51f09548b497/lists/89a7f58c-38fb-4dff-992d-4ab72d7c0d52/items/
I can got the items list which include the item id is needed.
Finally, my question is ,when I upload file to sharepoint, how can I got the item id which is needed by update item.
I ended up extracting the Item GUID from the response, i.e.
"#microsoft.graph.downloadUrl": "https://yeeofficesg.sharepoint.com/sites/GdTest/_layouts/15/download.aspx?UniqueId=b9d25e13-c915-432f-b9fb-f2d36a188d9f&Translate=false&tempauth=....
or
"eTag": ""{B9D25E13-C915-432F-B9FB-F2D36A188D9F},1""
or
"cTag": ""c:{B9D25E13-C915-432F-B9FB-F2D36A188D9F},1""
And then use that in the PATCH call where the item ID is required, i.e. https://graph.microsoft.com/v1.0/sites/abc78c05-a77b-45bf-a1a1-51f09548b497/lists/89a7f58c-38fb-4dff-992d-4ab72d7c0d52/items/**B9D25E13-C915-432F-B9FB-F2D36A188D9F**/fields
Might be a more elegant way to solve the problem, however this worked for me

Nested iteration over JSON using groovy closure in REST-assured

I have the following JSON response for my REST endpoint:
{
"response": {
"status": 200,
"startRow": 0,
"endRow": 1,
"totalRows": 1,
"next": "",
"data": {
"id": "workflow-1",
"name": "SampleWorkflow",
"tasks": [
{
"id": "task-0",
"name": "AWX",
"triggered_by": ["task-5"]
},
{
"id": "task-1",
"name": "BrainStorming",
"triggered_by": ["task-2", "task-5"]
},
{
"id": "task-2",
"name": "OnHold",
"triggered_by": ["task-0", "task-4", "task-7", "task-8", "task9"]
},
{
"id": "task-3",
"name": "InvestigateSuggestions",
"triggered_by": ["task-6"]
},
{
"id": "task-4",
"name": "Mistral",
"triggered_by": ["task-3"]
},
{
"id": "task-5",
"name": "Ansible",
"triggered_by": ["task-3"]
},
{
"id": "task-6",
"name": "Integration",
"triggered_by": []
},
{
"id": "task-7",
"name": "Tower",
"triggered_by": ["task-5"]
},
{
"id": "task-8",
"name": "Camunda",
"triggered_by": ["task-3"]
},
{
"id": "task-9",
"name": "HungOnMistral",
"triggered_by": ["task-0", "task-7"]
},
{
"id": "task-10",
"name": "MistralIsChosen",
"triggered_by": ["task-1"]
}
]
}
}
}
I am using rest-assured with a groovy gpath expression for an extraction as follows:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('task-3') }.name")
which correctly gives me [Mistral, Ansible, Camunda]
What I am trying to achieve is to find the task names that are triggered by the InvestigateSuggestions task. But I don't know for sure that the taskId I have to pass in to contains() is task-3; I only know its name i.e. InvestigateSuggestions. So I attempt to do:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
which does not work and complains that the parameter "response" was used but not defined.
How do I iterate over the outer collection from inside the findAll closure to find the correct id to pass into contains() ??
You can make use of a dirty secret, the restAssuredJsonRootObject. This is undocumented (and subject to change although it has never change as far as I can remember in the 7 year+ lifespan of REST Assured).
This would allow you to write:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(restAssuredJsonRootObject.response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
If you don't want to use this "hack" then you need to do something similar to what Michael Easter proposed in his answer.
When it comes to generating matchers based on the response body the story is better. See docs here.
I'm not sure if this is idiomatic but one approach is to find the id first and then substitute into another query:
#Test
void testCase1() {
def json = given()
.when()
.get("http://localhost:5151/egg_minimal/stacko.json")
// e.g. id = 'task-3' for name 'InvestigateSuggestions'
def id = json
.then()
.extract()
.path("response.data.tasks.find { it.name == 'InvestigateSuggestions' }.id")
// e.g. tasks have name 'task-3'
def tasks = json
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('${id}') }.name")
assertEquals(['Mistral', 'Ansible', 'Camunda'], tasks)
}

Logic App : Finding element in Json Object array (like XPath fr XML)

In my logic app, I have a JSON object (parsed from an API response) and it contains an object array.
How can I find a specific element based on attribute values... Example below where I want to find the (first) active one
{
"MyList" : [
{
"Descrip" : "This is the first item",
"IsActive" : "N"
},
{
"Descrip" : "This is the second item",
"IsActive" : "N"
},
{
"Descrip" : "This is the third item",
"IsActive" : "Y"
}
]
}
Well... The answer is in plain sight ... There's a FILTER ARRAY action, which works on a JSON Object (from PARSE JSON action).. couple this with an #first() expression will give the desired outcome.
You can use the Parse JSON Task to parse your JSON and a Condition to filter for the IsActive attribute:
Use the following Schema to parse the JSON:
{
"type": "object",
"properties": {
"MyList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Descrip": {
"type": "string"
},
"IsActive": {
"type": "string"
}
},
"required": [
"Descrip",
"IsActive"
]
}
}
}
}
Here how it looks like (I included the sample data you provided to test it):
Then you can add the Condition:
And perform whatever action you want within the If true section.

How to query by array of objects in Contentful

I have an content type entry in Contentful that has fields like this:
"fields": {
"title": "How It Works",
"slug": "how-it-works",
"countries": [
{
"sys": {
"type": "Link",
"linkType": "Entry",
"id": "3S5dbLRGjS2k8QSWqsKK86"
}
},
{
"sys": {
"type": "Link",
"linkType": "Entry",
"id": "wHfipcJS6WUSaKae0uOw8"
}
}
],
"content": [
{
"sys": {
"type": "Link",
"linkType": "Entry",
"id": "72R0oUMi3uUGMEa80kkSSA"
}
}
]
}
I'd like to run a query that would only return entries if they contain a particular country.
I played around with this query:
https://cdn.contentful.com/spaces/aoeuaoeuao/entries?content_type=contentPage&fields.countries=3S5dbLRGjS2k8QSWqsKK86
However get this error:
The equals operator cannot be used on fields.countries.en-AU because it has type Object.
I'm playing around with postman, but will be using the .NET API.
Is it possible to search for entities, and filter on arrays that contain Objects?
Still learning the API, so I'm guessing it should be pretty straight forward.
Update:
I looked at the request the Contentful Web CMS makes, as this functionality is possible there. They use query params like this:
filters.0.key=fields.countries.sys.id&filters.0.val=3S5dbLRGjS2k8QSWqsKK86
However, this did not work in the delivery API, and might only be an internal query format.
Figured this out. I used the following URL:
https://cdn.contentful.com/spaces/aoeuaoeua/entries?content_type=contentPage&fields.countries.sys.id=wHfipcJS6WUSaKae0uOw8
Note the query parameter fields.countries.sys.id

Resources