Do Azure Logic Apps support oneOf, anyOf in JSON schema validation - azure

I was trying to add JSON schema validation with in a Logic App using ParseJSON action.
I want to validate the existence of either of the object in the message (equivalent to XSD choice).
For instance, messages may have either of lastname or familyname.
{
"name": "Alan",
"familyname": "Turing"
}
Or
{
"name": "Alan",
"lastname": "Turing"
}
I modified the generated schema as,
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"oneOf": [
{
"lastname": {
"type": "string"
}
},
{
"familyname": {
"type": "string"
}
}
]
}
}
Logic App execution throws below error
Just to test if any other schema combination keywords works, tried to test with anyOf in place of oneOf and it fails in execution as well.
Does Logic Apps support these extended validation ? Am I missing some specific syntax here ?

If you are validating that either familyname or lastname be present then you are missing the "required" attribute.
{
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"oneOf": [
{
"familyname": {
"type": "string"
},
"required": [ "familyname" ]
},
{
"lastname": {
"type": "string"
},
"required": [ "lastname" ]
}
]
}
This will validate the JSON. If you want to get the values out in a later step you could use the coalesce function.
#coalesce(actionBody('Parse_JSON')?['familyname'], actionBody('Parse_JSON')?['lastname'])

Related

OpenAPI type schemas are written to the Swagger type field

My question is in regard to API schemas in Azure API Management, resource type Microsoft.ApiManagement/service/apis/schemas.
A schema created through the Azure Portal is created with the content type application/vnd.oai.openapi.components+json and written to document/components/schemas, which is the correct path for schema definitions in an OpenAPI definition.
Sample:
{
"value": [
{
"id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ApiManagement/service/xxx/apis/xxx/schemas/1629566051926",
"type": "Microsoft.ApiManagement/service/apis/schemas",
"name": "1629566051926",
"properties": {
"contentType": "application/vnd.oai.openapi.components+json",
"document": {
"components": {
"schemas": {
"patch-components-id-request-1": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"documentationURL": {
"type": "string"
},
"iacURL": {
"type": "string"
},
"duration": {
"type": "integer"
},
"statusID": {
"type": "integer"
},
"owner": {
"type": "string"
}
}
}
}
}
}
}
}
],
"count": 1
}
A schema created through the REST API or the Go SDK is set using properties.document.definitions, which leads to it being written to document/definitions, no matter the contentType.
Sample:
{
"value": [
{
"id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ApiManagement/service/xxx/apis/marble-dev-fctn/schemas/marbleschemas",
"type": "Microsoft.ApiManagement/service/apis/schemas",
"name": "marbleschemas",
"properties": {
"contentType": "application/vnd.oai.openapi.components+json",
"document": {
"definitions": {
"patch-components-id-request-1": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"documentationURL": {
"type": "string"
},
"iacURL": {
"type": "string"
},
"duration": {
"type": "integer"
},
"statusID": {
"type": "integer"
},
"owner": {
"type": "string"
}
}
}
}
}
}
}
],
"count": 1
}
When setting the contentType to application/vnd.ms-azure-apim.swagger.definitions+json this is fine, but when setting the contentType to application/vnd.oai.openapi.components+json two problems arise: The definition will not be included when exporting the OpenAPI Schema (at least when exporting from the Azure Portal, i have not tried any other way), since definitions is not a valid OpenAPI field, and it will not be shown in the Developer Portal.
As far as i understand it the definitons would need to be written to document/components/schemas for application/vnd.oai.openapi.components+json and document/definitions for application/vnd.ms-azure-apim.swagger.definitions+json.
I can import the definition to the correct path by setting it manually in an ARM Template or REST API call, but i am working on getting the terraform resource to work correctly, which is relying on the Go SDK. There might be a workaround for that as well but i would really like to find out if my understanding is wrong or if there might be a problem here.

Azure Logic Apps, Parsed JSON returning Null when used

I'm trying to access the values in JSON output that I received from two (2) Graph API calls, but each time I try to use them I get this error:
ExpressionEvaluationFailed. The execution of template action 'For_each' failed: the result of the evaluation of 'foreach' expression '#body('Parse_JSON_-_Managed_Devices')?['body']?['value']' is of type 'Null'. The result must be a valid array.
I have validated that my Graph API calls are properly formatted, and output is exactly what I'm expecting to be returned from both API calls. I get this error every time I either try to access the parsed JSON in an Azure Runbook or any other Logic App tasks.
I would love to know if someone has experienced this before and how it can be solved?
Graph query: https://graph.microsoft.com/beta/deviceManagement/managedDevices/?$select=id,userId,deviceName,userDisplayName,azureADDeviceId,managedDeviceName,emailAddress&$filter=operatingSystem eq 'windows'
JSON schema for managed devices
{
"properties": {
"body": {
"properties": {
"##odata.context": {
"type": "string"
},
"##odata.count": {
"type": "integer"
},
"##odata.nextLink": {
"type": "string"
},
"value": {
"items": {
"properties": {
"azureADDeviceId": {
"type": "string"
},
"deviceName": {
"type": "string"
},
"emailAddress": {
"type": "string"
},
"id": {
"type": "string"
},
"managedDeviceName": {
"type": "string"
},
"userDisplayName": {
"type": "string"
},
"userId": {
"type": "string"
}
},
"required": [
"id",
"userId",
"deviceName",
"userDisplayName",
"azureADDeviceId",
"managedDeviceName",
"emailAddress"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
}
Graph query: https://graph.microsoft.com/beta/users?$select=id,displayName,mail,officeLocation&$filter=accountEnabled eq true
JSON schema used for users
Graph query: https://graph.microsoft.com/beta/users?$select=id,displayName,mail,officeLocation&$filter=accountEnabled eq true
{
"properties": {
"body": {
"properties": {
"##odata.context": {
"type": "string"
},
"##odata.nextLink": {
"type": "string"
},
"value": {
"items": {
"properties": {
"displayName": {
"type": "string"
},
"id": {
"type": "string"
},
"mail": {
"type": "string"
},
"officeLocation": {
"type": "string"
}
},
"required": [
"id",
"displayName",
"mail",
"officeLocation"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
}

how to access json within http trigger

How do I get the subject property from the payload below ?
I've got an http-triggered logic app:
I want to be able to grab the contents of the subject property.
The schema as shown above in the image looks like this:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"topic": {
"type": "string"
},
"subject": {
"type": "string"
},
"eventType": {
"type": "string"
},
"eventTime": {
"type": "string"
},
"id": {
"type": "string"
},
"data": {
"type": "object",
"properties": {
"api": {
"type": "string"
},
"clientRequestId": {
"type": "string"
},
"requestId": {
"type": "string"
},
"eTag": {
"type": "string"
},
"contentType": {
"type": "string"
},
"contentLength": {
"type": "integer"
},
"blobType": {
"type": "string"
},
"url": {
"type": "string"
},
"sequencer": {
"type": "string"
},
"storageDiagnostics": {
"type": "object",
"properties": {
"batchId": {
"type": "string"
}
}
}
}
},
"dataVersion": {
"type": "string"
},
"metadataVersion": {
"type": "string"
}
},
"required": [
"topic",
"subject",
"eventType",
"eventTime",
"id",
"data",
"dataVersion",
"metadataVersion"
]
}
}
How do I get the subject property from this payload?
Go to your logic app designer in the azure portal and you can specifically assign the json to variables in your flow process
Here is the link on how to do this
With the Request trigger, if you want to get the property, you need pass the Request Body into json cause the triggerBody() value is in a String type, it doesn't support select the property. Set the parse json action like the below pic.
Then your json set the data in array type, that's another problem you will encounter. So when you select property you need add the index like the below with Expression: body('Parse_JSON')[0]['subject'].
I test with short json two properties subject and topic.

Include `meta` member in resource identifiers in `relationships` object

From my understanding of the JSON:API spec (specifically https://jsonapi.org/format/#document-resource-object-linkage) I should be able to include meta members for each member of a relationship.
I have been able to add a hash of meta data to the relationships object itself, but not one to each of the individual relationships within.
class PlanSerializer < ApplicationSerializer
attributes :id, :name
has_many :features do
meta value: "x"
end
end
I know I can use a block syntax for has_many, and think that's the way to achieve this. But I haven't got it working. Calling the meta method within the block adds the meta block to the features relationship object, and I need to add one to each entry in that array.
My questions:
Have I understood the spec correctly? Should I be able to add a meta object to each relationship?
How would I go about doing this with the active model serializers?
Background:
My goal is to represent a many-many from Plans to Features where each plan might have some extra information for it's own relationship to a given Feature (and that information is different for every Plan, so it doesn't belong on the Feature object)
If your answer is that I shouldn't be doing this, that's fine, but please present an alternative which you think is preferred.
// My desired output
{
"data": [
{
"id": "small",
"type": "plans",
"attributes": {
/* Some attributes */
},
"relationships": {
"features": {
"data": [
{
"id": "num-users",
"type": "features",
"meta": {
"value": 1
}
},
{
"id": "num-projects",
"type": "features",
"meta": {
"value": 5
}
}
]
}
}
},
{
"id": "large",
"type": "plans",
"attributes": {
/* Some attributes */
},
"relationships": {
"features": {
"data": [
{
"id": "num-users",
"type": "features",
"meta": {
"value": 5
}
},
{
"id": "num-projects",
"type": "features",
"meta": {
"value": 50
}
},
{
"id": "unlimited-downloads",
"type": "features"
}
]
}
}
}
],
"included": [
{
"id": "num-users",
"type": "features",
"attributes": {
"description": "Number of users"
}
},
{
"id": "num-projects",
"type": "features",
"attributes": {
"description": "Number of projects"
}
},
{
"id": "unlimited-downloads",
"type": "features",
"attributes": {
"description": "Unlimited downloads"
}
}
]
}

Missing Subscription Key field in Swagger API connector (trough Azure API Management) in Logic App

I have created a REST API with a Swagger/OPEN API specification which I will like to consume trough a Azure API Management tenant in a Logic App.
When I download the specification it looks like this:
{
"swagger": "2.0",
"info": {
"title": "Leasing",
"version": "1.0"
},
"host": "ENDPOINT.azure-api.net",
"basePath": "/leasing",
"schemes": [
"http",
"https"
],
"securityDefinitions": {
"apiKeyHeader": {
"type": "apiKey",
"name": "Ocp-Apim-Subscription-Key",
"in": "header"
},
"apiKeyQuery": {
"type": "apiKey",
"name": "subscription-key",
"in": "query"
}
},
"security": [
{
"apiKeyHeader": []
},
{
"apiKeyQuery": []
}
],
"paths": {
"/{Brand}/groups": {
"get": {
"description": "Get a list of leasing groups on a brand",
"operationId": "GetGroups",
"parameters": [
{
"name": "Brand",
"in": "path",
"description": "Selection of possible brands",
"required": true,
"type": "string",
"enum": [
"Volkswagen",
"Audi",
"Seat",
"Skoda",
"VolkswagenErhverv",
"Porsche",
"Ducati"
]
}
],
"responses": {
"200": {
"description": "Returns a list of leasing groups",
"schema": {
"$ref": "#/definitions/GroupArray"
}
},
"400": {
"description": "If the brand is not valid",
"schema": {
"$ref": "#/definitions/Error"
}
}
},
"produces": [
"application/json"
]
}
}
},
"definitions": {
"Group": {
"type": "object",
"properties": {
"id": {
"format": "int32",
"type": "integer"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"leasingModelCount": {
"format": "int32",
"type": "integer"
},
"lowestMonthlyFee": {
"format": "int32",
"type": "integer"
}
}
},
"Error": {
"type": "object",
"properties": {
"code": {
"enum": [
"NotValidBrand",
"NotValidGroupId"
],
"type": "string",
"x-ms-enum": {
"name": "ErrorCode",
"modelAsString": true
}
},
"message": {
"type": "string"
}
}
},
"GroupArray": {
"type": "array",
"items": {
"$ref": "#/definitions/Group"
}
}
}
}
When I add this in a Logic App with the connector HTTP + Swagger I only get to define the {Brand} query input but not the various ways of using the Subscriptions key (header or query) as defined in SecurityDefiniations.
The whole securityDefinitions and security section are automatically generated in the Azure API Management service, but not recognized in Logic App.
See image of missing subscription key field:
What am I doing wrong?
Update
I have tried the following:
Usage of the 'Authentication' field (but this field is limited to certain types of auths flows https://learn.microsoft.com/en-us/azure/connectors/connectors-native-http#authentication)
Change the Logic App 'Http + Swagger'-action in code to add the header parameter, but this action converts the action to a simple 'Http' action and therfore loosing the automatic schema generation from Swagger.
I think you need to specify this in the Authentication-field in a JSON format. Something like:
{
"apiKeyHeader" : "your Ocp-Apim-Subscription-Key",
"apiKeyQuery" : "your subscription key"
}

Resources