How to describe request body properly using OpenAPI and API Platform? - symfony

I am struggling getting the right definition for the request body used from within Symfony Api Platform:
From the image above, what my endpoint is expecting is a JSON containing required values. I am defining required values to be in the path but that is NOT true and they don't belong even to: query, header or cookies.
I have tried two definitions (and I've removed some lines that aren't relevant for the resolution):
// the definition result is on the first image on this post
resources:
App\Entity\Cases:
collectionOperations:
case_assign:
swagger_context:
parameters:
- name: assign_type
in: path
description: 'The assignee type: worker or reviewer'
required: true
type: string
// ....
- in: body
name: body
description: 'Object needed to perform a case assignment'
required: true
example: {
"assign_type": "worker",
"assigned_by": 1,
"assigned_to": 1,
"cases": {
"0": 109855,
"1": 109849,
"2": 109845
}
}
And the second definition looks like:
resources:
App\Entity\Cases:
collectionOperations:
case_assign:
swagger_context:
summary: 'Assign a worker or a reviewer to a case'
parameters:
- name: body
in: body
required: true
schema:
type: array
items:
assign_type:
name: assign_type
description: 'The assignee type: worker or reviewer'
required: true
type: string
And here is the result:
None of them seem to be doing what I need or expect, what I am doing wrong? Can I get some help?
I have also read several pages/post without found a good example or the right way to do it (see the following list):
https://github.com/api-platform/api-platform/issues/1019
https://api-platform.com/docs/core/swagger/
https://idratherbewriting.com/learnapidoc/pubapis_swagger_intro.html
https://swagger.io/docs/specification/describing-parameters/
https://swagger.io/docs/specification/describing-request-body/
How to describe this POST JSON request body in OpenAPI (Swagger)?

You can use a SwaggerDecorator as described in the docs to override the generated swagger.json and change pretty much anything you like. You will need to edit the definitions for v2
"paths": {
"/todos": {
"post": {
"parameters": [
{
"name": "todo",
"in": "body",
"description": "The new Todo resource",
"schema": {
"$ref": "#/definitions/Todo"
}
}
]
}}}
"definitions": {
"Todo": {
"type": "object",
"description": "",
"properties": {
"text": {
"required": true,
"description": "This text will be added to the schema as a description",
"type": "string"
},...
or the components.schemas in Openapi v3:
"components": {
"schemas": {
"Todo": {
"type": "object",
"description": "",
"properties": {
"text": {
"required": true,
"minLength": 4,
"example": "some example text",
"description": "This text will be added to the schema as a description",
"type": "string"
},...
Your other option is to use the "swagger_context" ("openapi_context" for openapi v3) of the #ApiResource or #ApiProperty Annotations. Valid options should be in the swagger docs.
/**
* This text will be added to the schema as a description
* #ApiProperty(
* swaggerContext={"required"=true},
* openapiContext={"required"=true, "minLength"=4, "example"="some example text"})
* #ORM\Column(type="string", length=255)
*/
private $text;
Would result in:
example doc
Edit:
I just noticed that there is an error in your yaml configuration. You are trying to setup the documentation for an array. I assume you want to actually send an object
parameters:
- name: body
in: body
required: true
schema:
type: object
required: #only for swagger v2
- assign_type
properties:
assign_type:
description: 'The assignee type: worker or reviewer'
required: true #only for openapi v3
type: string
assigned_by:
...
You can check the correct syntax for Data Types here.

Related

HAPI FHIR try to use patch

I've this resource of type Paramaters as follow:
{
"resourceType": "Parameters",
"parameter": [
{
"name": "operation",
"part": [
{
"name": "type",
"valueCode": "add"
},
{
"name": "path",
"valueString": "Organization"
},
{
"name": "name",
"valueString": "active"
},
{
"name": "value",
"valueString": "true"
}
]
}
]
}
Because I want to add active value on my Organization.
So I write, in according with HAPI FHIR documentation - 4.2.7 paragraph, this code to execute a patch:
fhirClientR4Configuration.clientFhihrR4().patch().withBody(body).withId("Organization/2381").execute();
But I have this error:
ca.uhn.fhir.rest.server.exceptions.InvalidRequestException: HTTP 400 :
Cannot deserialize instance of
java.util.ArrayList<com.github.fge.jsonpatch.operation.JsonPatchOperation>
out of FIELD_NAME token at [Source: UNKNOWN; line: -1, column: -1]
I've noticed I must put in the same array all informations about patch (in the tag part), but I don't know I can resolve it.
Tha HAPI FHIR version is 4.2.0

Api gateway get item dynamodb configuration

Hi i need get an item from dynamodb through api gateway and i configure the resources like this:
i configure the integration method like the next picture:
and the mapping template is like this:
but when i test apigateway launch this error
Execution failed due to configuration error:
No match for output mapping and no default output mapping configured.
Endpoint Response Status Code: 200
Gateway response type: API_CONFIGURATION_ERROR with status code: 500
I followed these two tutorials and performed get on my dynamoDB table.
My table has primary key name "pk".
Tutorials: Video & Blog
If i write my dynamo request body like yours it does not fetch any record
{
"TableName": "apiG",
"Key": {
"pk": {
"S": "key1"
}
}
}
But if I form my request like
{
"TableName": "apiG",
"PrimaryKey": "pk",
"KeyConditionExpression": "pk = :v1",
"ExpressionAttributeValues": {
":v1": {
"S": "key1"
}
}
}
I get the desired response from dynamoDB.
Your error looks like you have some mix up in your integration response and method response. In the simplest form, keep your method response as default i.e. "HTTP Status: 200 Models: application/json => Empty" and leave your integration response as API Gateway console creates it for you.
This will make sure your DynamoDB output is sent without modification to your browser/output.
I transformed my dynamo output using following mapping template in integration response.
#set($inputRoot = $input.path('$'))
{
"content": [
#foreach($elem in $inputRoot.Items) {
"key": "$elem.pk.S",
"value": "$elem.pv.S"
}#if($foreach.hasNext),#end
#end
]
}
and it produced following output.
{
"content": [
{
"key": "key1",
"value": "val1"
}
]
}
P.S. i had a dynamo table named 'apiG' with primaryKey 'pk' and following the exported swagger from my experiment. Hope it helps.
openapi: "3.0.1"
info:
title: "dynamoProxy"
version: "2020-05-01T06:45:38Z"
servers:
- url: "https://aaaaaaaaaa.execute-api.us-east-2.amazonaws.com/{basePath}"
variables:
basePath:
default: "/test"
paths:
/db:
get:
responses:
200:
description: "200 response"
content:
application/json:
schema:
$ref: "#/components/schemas/Empty"
x-amazon-apigateway-integration:
credentials: "arn:aws:iam::111111111111:role/apiGddbRole"
uri: "arn:aws:apigateway:us-east-2:dynamodb:action/Query"
responses:
default:
statusCode: "200"
responseTemplates:
application/json: "#set($inputRoot = $input.path('$'))\n{\n \"content\"\
: [\n #foreach($elem in $inputRoot.Items) {\n \"\
key\": \"$elem.pk.S\",\n \"value\": \"$elem.pv.S\"\n \
\ }#if($foreach.hasNext),#end\n\t#end\n ]\n}"
passthroughBehavior: "when_no_templates"
httpMethod: "POST"
requestTemplates:
application/json: "{\n \"TableName\": \"apiG\",\n \"PrimaryKey\":\
\ \"pk\",\n \"KeyConditionExpression\": \"pk = :v1\",\n \"ExpressionAttributeValues\"\
: {\n \":v1\": {\n \"S\": \"key1\"\n }\n }\n\
}"
type: "aws"
components:
schemas:
Empty:
title: "Empty Schema"
type: "object"
Cheers!

JAGQL - Why do I need an id for a post call?

I'm using JAGQL to build a JSON API compatible express server. My database behind it is MongoDB (jsonapi-store-mongodb). I posted my question here as well: https://github.com/holidayextras/jsonapi-store-mongodb/issues/59
According to the JAGQL documentation, https://jagql.github.io/pages/project_setup/resources.html#generateid,
I am told that
generateId
By default, the server autogenerates a UUID for resources which are created without specifying an ID. To disable this behavior (for example, if the database generates an ID by auto-incrementing), set generateId to false. If the resource's ID is not a UUID, it is also necessary to specify an id attribute with the correct type. See /examples/resorces/autoincrement.js for an example of such a resource.
But when I send a POST request to one of my resources, I get this:
"jsonapi": {
"version": "1.0"
},
"meta": {},
"links": {
"self": "/myresource"
},
"errors": [
{
"status": "403",
"code": "EFORBIDDEN",
"title": "Param validation failed",
"detail": [
{
"message": "\"id\" is required",
"path": [
"id"
],
"type": "any.required",
"context": {
"key": "id",
"label": "id"
}
}
]
}
]
What am I missing?
See here for more details: https://github.com/jagql/framework/issues/106
In your resource definition, you want to add primaryKey: 'uuid':
{
resource: 'things',
handlers,
primaryKey: 'uuid',
attributes: {
...
}
}

JSON API format in API-Platform

First of all I want to implement JSON API.
I follow tutorial on api platform and just like in example create entities and response is like
{
"links": {
"self": "/api/books"
},
"meta": {
"totalItems": 1,
"itemsPerPage": 30,
"currentPage": 1
},
"data": [
{
"id": "/api/books/1",
"type": "Book",
"attributes": {
"isbn": "9781782164104",
"title": "Persistence in PHP with the Doctrine ORM",
"description": "This book is designed for PHP developers and architects who want to modernize their skills through better understanding of Persistence and ORM.",
"author": "Kévin Dunglas",
"publicationDate": "2013-12-01T00:00:00+01:00",
"_id": 1
},
"relationships": {
"reviews": {
"data": [
{
"type": "Review",
"id": "/api/reviews/1"
}
]
}
}
}
]
}
My api_platform.yaml config
api_platform:
mapping:
paths: ['%kernel.project_dir%/src/Entity']
formats:
jsonapi:
mime_types: ['application/vnd.api+json']
So i have problem with id filed in data. I get id fields in format api/entityName/id but I just want to get number(string), just like in JSON API. So is there some configuration that i miss or is any way to achieve that
It was discussed here.
You need to use Normalizer or create custom getter.
All you need is to send
Accept: application/json
on request header.

Elastic search language configuration

I work on a project with symfony and sonata admin,
my project will be in two language: fr and de so i used elastic search so i installed "friendsofsymfony/elastica-bundle": "3.2.1".
in the elasticconfiguration file how can add the language configuration?
this is my fos elastic bundle configuration file:
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
indexes:
myproject:
settings:
index:
analysis:
analyzer:
custom_analyzer :
type : custom
tokenizer: nGram
filter : [stopwords, asciifolding ,lowercase, elision, worddelimiter]
custom_search_analyzer :
type : custom
tokenizer: standard
filter : [stopwords, asciifolding ,lowercase, elision, worddelimiter]
tokenizer:
nGram:
type: nGram
min_gram: 3
max_gram: 20
filter:
elision:
type: elision
articles: [l, m, t, qu, n, s, j, d]
stopwords:
type: stop
stopwords: [_french_]
ignore_case : true
worddelimiter:
type: word_delimiter
types:
produit:
mappings:
titre: ~
active:
type: boolean
descriptifTexteOriginal:
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
type: string
norms: { enabled: false }
explain: true
index_options: freqs
persistence:
driver: orm
model: myproject\BOBundle\Entity\Produit
finder: ~
provider: ~
listener: ~
In base, we will about two situtaion. First one is you have a field and it can store
two or more different language text. For example, you have a title field which can
store english or turkish. Not both of them is at the same time. The second situation
is, your data have multiple language value in one document.
In my opinion, there is two way of this problem, too. First is separate your fields
and second is separating index. Let's explain both of them to you:
Think about you have the following data for your products on e-commerce website:
id => identify of your data
name => name of the product
price => price of the product
Our first opinion has multiple option. Now, let's look our first option of the first
opinion and create a mapping:
PUT 44369578
{
"mappings": {
"product": {
"properties": {
"id": { "type": "integer" },
"name": {
"type": "text",
"fields": {
"en": {
"type": "text",
"analyzer": "englishAnalyzer"
},
"tr": {
"type": "text",
"analyzer": "turkishAnalyzer"
}
}
},
"price": { "type": "double"}
}
}
}
}
There is a name field which can take english or turkish value
And in this field only can handle one of them. Not both of them
When you try to improve your language support, you should change your mapping, too.
Then, let's look our second options of the first opinion.
PUT 44369578
{
"mappings": {
"product": {
"properties": {
"id": { "type": "integer" },
"name_en": {"type": "text", "analyzer": "englishAnalyzer" },
"name_tr": {"type": "text", "analyzer": "turkishAnalyzer" },
"price": { "type": "double"}
}
}
}
}
In this example there is two field for our two language. And we can
save english and turkish values for our documents at the same time.
When you try to improve your language support, you should change your mapping, too.
These are two options of the first opinion.
Now, lets look our second opinion. In this example, we have same data structure for
product documents. But we create multiple indexes for each languages.
PUT 44369578
{
"mappings": {
"product": {
"properties": {
"id": { "type": "integer" },
"name": {"type": "text", "analyzer": "englishAnalyzer" },
"price": { "type": "double"}
}
}
}
}
PUT 44369578
{
"mappings": {
"product": {
"properties": {
"id": { "type": "integer" },
"name": {"type": "text", "analyzer": "turkishAnalyzer" },
"price": { "type": "double"}
}
}
}
}
In this opinion, we have two documents for each document and we try to merge the
documents on our application while we are searching documents. This is odd part of
this opinion. But we can create a new index while we create a new language support.
Conclusion, As far as, I know these three methods. You can select one of them and
don't forget, each election will get some features but take away some features.

Resources