Validate the json Array with Either one field required in Mule 4 - mule

Request Json Looks like the below :-
{
"eNumber": 8506493,
"details": [
{
"id":12345,
"name": xyz123
}
]
}
As part of requirement, I need to check the "details" array that either "id" or "name" field must present. if "id" field is present, "name" is non-mandatory. if "name" field is present, "id" is non-mandatory. Throws error if not met.
I tried few options using filter the details array and check the size of the filtered array in the validation component. It does not seems to be working well. if anyone has got better solutions.please share it here.

This example code will return true or false if it passes your condition
%dw 2.0
import * from dw::core::Arrays
output application/json
---
payload.details every ((item) -> item.id? or item.name?)
The function I'm using is every that checks that all elements in an array passes the given criteria.
Later you can use a choice and a use the raise error or you can use the fail dw function with an if else.

You can restrict it at RAML level.
Sample RAML -
#%RAML 1.0
title: api
types:
test1:
type: object
properties:
id:
type: string
example: 123a
test2:
type: object
properties:
name:
type: string
example: xyz124
test3:
type: object
properties:
enumber:
type: string
example: 8506493a
details :
type: [test1 | test2]
/test:
post:
body:
application/json:
type: test3

Related

How can I retrieve nested values in Keystone 5 for my list

I'm adding a list called 'tourlocation' to my Keystone 5 project. In my mongo database my tourlocations collection has an object called 'coordinates', with two values: 'lat' and 'long'. Example:
"coordinates" : {
"lat" : 53.343761,
"long" : -6.24953
},
In the previous version of keystone, I could define my tourlocation list coordinates object like this:
coordinates: {
lat: {
type: Number,
noedit: true
},
long: {
type: Number,
noedit: true
}
Now unfortunately, when I try to define the list this way it gives the error: The 'tourlocation.coordinates' field doesn't specify a valid type. (tourlocation.coordinates.type is undefined)'
Is there any way to represent objects in keystone 5?
#Alex Hughes I believe your error says "type" which you may need to add it like this
keystone.createList('User', {
fields: {
name: { type: Text }, // Look at the type "Text" even in the MongoDB you can choose the type but it will be better to choose it here from the beginning.
email: { type: Text },
},
});
Note that noedit: true is not supported in version 5 of KeystoneJS.
For more info look at this page https://www.keystonejs.com/blog/field-types#core-field-types

RAML Max length of an item in a String array

I am defining a RAML spec. I have an attribute to hold an array of string. I want to make a rule that a string value in the array can have only maximum 3 charactors only (For example: regions: ["wes","nrh"] is valid. regions: ["lenghthyvalue", "anotherLenghthyvalue"] invalid). How can I handle it in RAML. My current code is as following:
regions:
type: string []
required: true
Available attributes are maxItems only. How to limit the character length of an item ?
I use raml 1.0
First create a string type that has maxLength and minLength attributes. Then you can reference that type in your array type instead of just a string array. Example:
#%RAML 1.0
title: test
version: 1.0
types:
region:
type: string
minLength: 3
maxLength: 3
regions:
type: region []
required: true
/test:
get:
queryParameters:
regions: region

How to define an example request body containing an array of complex objects in Swagger?

I am trying to write the Swagger spec for a service that posts an array of objects as request body. I would like the user to be able to test the service with a specific set of multiple different complex objects in the array as the default sample inputs.
So far I have the following code defining the service and complex object:
paths:
/myService
post:
summary: test 123
description: test 123
parameters:
- name: bodyParamsObject
description: 'Object containing any / all params in the body'
in: body
required: true
schema:
properties:
data:
$ref: '#/definitions/myInputArray'
responses:
200:
description: OK
schema: myOutputArray
definitions:
myInputArray:
type: array
items:
$ref: '#/definitions/myComplexObject'
myOutputArray:
type: array
items:
$ref: '#/definitions/myComplexObject'
myComplexObject:
type: object
properties:
description:
type: string
example: 'Example Item'
size:
example: 552
type: integer
format: int32
hasAdditionalProperties:
type: boolean
example: true
The output array is coming back correctly, but there is only one item in the model schema.
How can I make the sample request body contain multiple different items in the array?
I was able to solve this by using the example property on the object definition and filling it with the array in json.
definitions:
myInputArray:
type: array
items:
$ref: '#/definitions/myComplexObject'
example: [
{
"description": "Example Item 1",
"hasAdditionalProperties": true,
"size": 750,
},
{
"description": "Another example",
"hasAdditionalProperties": false,
"size": -22,
},
{
"description": "Last one",
"hasAdditionalProperties": true,
"size": 0,
}
]
myComplexObject:
type: object
properties:
description:
type: string
example: 'Example Item'
size:
example: 552
type: integer
format: int32
hasAdditionalProperties:
type: boolean
example: true

Merge two JSON outputs into one with Dataweave

I currently have two JSON files with data.
The first has a list of actions by a user. However, the userID is a UID string instead of their user name.
The second is a JSON list of UID strings with their corresponding user names. I stored this JSON in a Flow Variable named UserPayload
I'd like to merge the user name into the first list so that my output has actual users names instead of the UID.
Here is what I had so far...but the userId part doesn't work since my flowVar is an list.
%dw 1.0
%output application/csv
---
payload map ((payload01, indexOfPayload01) -> {
user: payload.01.userId,
actions: payload01.action,
FileName: payload01.payload.properties.name default "N/A",
userId: flowVars.UserPayload.objectName
})
Any help would be appreciated. Thanks!
you can access the right object from the UserPayload flowVar by either filtering the content of UserPayload based on userId or creating a associative array from UserPayload.
filtering UserPayload
%dw 1.0
%output application/json
---
payload map (action, index) -> {
user: action.user,
action: action.action,
FileName: action.FileName,
userId: (flowVars.UserPayload filter $.objectId == action.user)[0].objectName
}
associative array
%dw 1.0
%output application/json
%var users = flowVars.UserPayload groupBy $.objectId
---
payload map (action, index) -> {
user: action.user,
action: action.action,
FileName: action.FileName,
userId: users[action.user][0].objectName
}
for my examples i used following sample data derived from your question.
flowVars.UserPayload
[{
"objectId": "0000-0000-0001",
"objectName": "first user"
}, {
"objectId": "0000-0000-0002",
"objectName": "second user"
}]
payload
[{
"user": "0000-0000-0001",
"action": "some crazy action",
"FileName": "some-crazy-action.mov"
}]

Mule Dataweave Fixed Width File with header and footer

I am working on a project where we receive a flat file but the first and last lines have information that does not fit the fixed width pattern. Is there a way to dataweave all of this information correctly and if possible put the header and footer into variables and just have the contents in the payload.
Example File
HDMTFSBEUP00000220170209130400 MT HD07
DT01870977 FSFSS F3749261 CR00469002017020820170225 0000
DT01870978 FSFSS F3749262 CR00062002017020820170125 0000
TRMTFSBEUP00000220170209130400 000000020000002000000000000043330000000000000 0000
I know for CSV you can skip a line but dont see it with fixed width and also the header and footer will both start with the first 2 letters every time so maybe they can be filtered by dataweave?
Please refer to the DataWeave Flatfile Schemas documentation. There are several examples for processing several different types of data.
In this case, I tried to simplify your example data, and apply a custom schema as follow:
Example data:
HDMTFSBEUP00000220170209130400
DT01870977
DT01870978
TRMTFSBEUP00000220170209130400
Schema/Flat File Definition:
form: FLATFILE
structures:
- id: 'test'
name: test
tagStart: 0
tagLength: 2
data:
- { idRef: 'header' }
- { idRef: 'data', count: '>1' }
- { idRef: 'footer' }
segments:
- id: 'header'
name: header
tag: 'HD'
values:
- { name: 'header', type: String, length: 39 }
- id: 'data'
name: data
tag: 'DT'
values:
- { name: 'code', type: String, length: 17 }
- id: 'footer'
name: footer
tag: 'TR'
values:
- { name: 'footer', type: String, length: 30 }
The schema will validate the example data and identify based on the tag, the first 2 letters. The output will be grouped accordingly.
{
"header": {},
"data": [{}, {}],
"footer": {}
}
Since the expected result is only the data, then just select it: payload.data.
Use range selector to skip header and footer.
payload[1..-2] map {
field1: $[0..15],
field2: $[16..31]
...,
...
}
[1..-2] will select from 2nd line till the second last line in the payload.
$[0..15] will select from 1st column index to 16th index. $[16..31] select from 17th column index to 32nd index.
I was facing the same issue and the answer #sulthony h wrote needs a little tweak. I used these lines instead and it worked for me.
data:
- { idRef: 'header', count: 1 }
- { idRef: 'data', count: '>1' }
- { idRef: 'footer', count: 1 }
"count" was missing from header and footer, and that was throwing an exception. Hope this helps.