validate json object with varying properties - javascript

I have json object whose property values are unique and can be anything;
{
"cat1": {
"name": "kitty",
"type": "animal",
"color": "ginger"
},
"dog2": {
"name": "ripple",
"type": "animal",
"color": "black"
},
"book10": {
"name": "myBook",
"type": "book",
"color": "NA"
},
"orange6": {
"name": "NA",
"type": "fruit",
"color": "orange"
},
"pig1":{
"name": "spring",
"type": "animal",
"color": "pink"
}
}
Now I'm confused how to write its validation schema. Does anybody know how to do it?
var mySchema = {
"type": "object",
"properties": {
// no idea how to check varying properties like cat1, dog2, etc. which might change next time
}
}

You can try this
var mySchema = {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"name": { "type": "string"},
"type": { "type": "string"},
"color": { "type": "string"},
}
}
}
ref: JSONSchema how to define a schema for a dynamic object

Related

How to dynamically create and iterate Json Object inside a Json Array using Postman - Javascript

I have a payload like mentioned below :
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
},
{
"id": "1004",
"type": "Devil’sFood"
}
]
},
"topping": [
{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "PowderedSugar"
},
{
"id": "5006",
"type": "ChocolatewithSprinkles"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
}
**I want to increment the json objects dynamically(it can be a duplicate as well) which is inside the array topping based on the array size. For example if mention the array size as topping[10] it is suppose to create a payload of 10 objects and push those 10 objects of similar type inside the array topping ** Is it possible to dynamically create json objects and post the request in postman??
Kind note : The size of the array should be parameterized. Please let me know.
Please find the image highlighted in green. I want to dynamically increase the payload(topping array size based on the index using postman
You could do this:
Tab Pre-request
let req = {
"id": "0001",
"type": "donut",
"topping": []
};
let numberOfTopping = 5;
for (let i = 0; i < numberOfTopping; i++) {
let toppingItem = {
"id": `${_.random(5001, 5010)}`,
"type": `${_.sample(["Glazed", "Sugar", "None"])}`
};
req.topping[i] = toppingItem;
}
pm.variables.set("req", JSON.stringify(req));
Tab body
Result
{
"id": "0001",
"type": "donut",
"topping": [
{
"id": "5006",
"type": "Glazed"
},
{
"id": "5001",
"type": "Sugar"
},
{
"id": "5006",
"type": "Glazed"
},
{
"id": "5006",
"type": "None"
},
{
"id": "5008",
"type": "Sugar"
}
]
}

Create object paths from a deeply nested object (Schema)

I have an avro schema, which is a deeply nested object with the same (sub)-structure. It looks like this:
{
"type": "record",
"namespace": "company.car.v1",
"name": "CarV1",
"fields": [
{
"name": "plateNumber",
"type": "string"
},
{
"name": "ownerId",
"type": "string",
"keepThisField": "true"
},
{
"name" : "details",
"keepThisField": "true"
"type" : {
"type" : "record",
"name" : "DetailsV1",
"fields" : [
{
"name": "engine",
"type": {
"type": "record",
"name": "EngineV1",
"fields": [
{
"name": "size",
"type": "int",
"default": 0,
"keepThisField": "true"
},
{
"name": "valvesCount",
"type": "int",
"default": 0
}
]
}
},
{
"name" : "color",
"type" : "string",
"default" : "NONE"
},
{
"name" : "rimSize",
"type" : "int",
"default" : "NONE"
}
]},
"default" : {}
},
{
"name": "isBrandNew",
"type": "boolean"
}
]
}
I want to be able to generally get all the object paths of this object (Schema) in JavaScript. So having something like a extractPaths(avroSchema) which for the example above would return:
[
"plateNumber",
"ownerId",
"details.engine.size",
"details.engine.valvesCount",
"details.color",
"details.rimSize",
"isBrandNew"
]
The order of the strings does not matter obviously. Anyone has an idea how this can be achieved in JavaScript?
Use a recursive generator function for generate path string.
var schema = { "type": "record", "namespace": "company.car.v1", "name": "CarV1", "fields": [{ "name": "plateNumber", "type": "string" }, { "name": "ownerId", "type": "string", "keepThisField": "true" }, { "name": "details", "keepThisField": "true", "type": { "type": "record", "name": "DetailsV1", "fields": [{ "name": "engine", "type": { "type": "record", "name": "EngineV1", "fields": [{ "name": "size", "type": "int", "default": 0, "keepThisField": "true" }, { "name": "valvesCount", "type": "int", "default": 0 }] } }, { "name": "color", "type": "string", "default": "NONE" }, { "name": "rimSize", "type": "int", "default": "NONE" }] }, "default": {} }, { "name": "isBrandNew", "type": "boolean" }] }
function* extractPaths(schema, value) {
for (const { name, type } of schema.fields) {
let path = value ? `${value}.${name}` : name
if (typeof type == "object")
yield* extractPaths(type, path);
else
yield path
}
}
console.log([...extractPaths(schema)]);

Form multiple groups for a complex object in uiSchema

Description
I'm using library react-json-schema to display JSON schema as a form.
I have a requirement, where the form is very large, hence I'm using uiSchema groups to form the tabs. But one of my attributes, which is an object, contains many objects. I want to spread these child objects further into the tabs.
I used the code suggested in #784 . I went through GroupedSchema code and it checks only in properties of schema, if the given field is present or not. It doesn't go deep down inside a nested object.
Steps to Reproduce
1.A dummy Schema:
{
"A": {
"type": "string",
"title": "A"
},
"B": {
"type": "string",
"title": "B"
},
"C": {
"type": "string",
"title": "C"
},
"D": {
"type": "object",
"properties": {
"DA": {
"type": "object",
"properties": {
"DAA": {
"type": "string",
"title": "DAA"
},
"DAB": {
"type": "string",
"title": "DAB"
}
}
},
"DB": {
"type": "object",
"properties": {
"DBA": {
"type": "string",
"title": "DBA"
},
"DBB": {
"type": "string",
"title": "DBB"
}
}
},
"DC": {
"type": "object",
"properties": {
"DCA": {
"type": "string",
"title": "DCA"
},
"DCB": {
"type": "string",
"title": "DCB"
}
}
}
}
}
}
Expected behavior
I'm trying to get tabs for A,B,C,DA,DB,DC
Here is the link to codesandbox

Why data is doubled, how I can fix it?

Good afternoon.
I have required json, which contains the basic template for the layout of Adaptive Cards (bot framework).
Here's this json:
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0",
"type": "AdaptiveCard",
"speak": "",
"body": [
{
"type": "TextBlock",
"horizontalAlignment": "center",
"text": "Все машины",
"weight": "bolder",
"isSubtle": false
},
{
"type": "TextBlock",
"text": "Внимание, вы вошли в режим тендера.",
"separator": true
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Подтвердить лот(ы)",
"data": {
"msteams": {
"type": "messageBack",
"displayText": "Идет подтверждение ваших лотов, ожидайте!",
"text": "/accept",
"value": "{\"x\": \"bfVal\", \"y\": \"from value\"}"
}
}
},
{
"type": "Action.Submit",
"title": "Отменить все лоты",
"data": {
"x": "123",
"msteams": {
"type": "messageBack",
"displayText": "Идет отменение ваших лотов, ожидайте!",
"text": "/cancel",
"value": "{\"bfKey\": \"bfVal\", \"conflictKey\": \"from value\"}"
}
}
}
]
}
I also have a loop that takes data from my source and forms another json from it.
try {
// Pull in the data from Microsoft Graph.
const client = new SimpleGraphClient(tokenResponse.token);
const me = await client.getList();
var i = 0;
while (i < me['value'].length) {
feed = {
"type": "ColumnSet",
"separator": true,
"columns": [
{
"type": "Column",
"width": 1,
"items": [
{
"type": "TextBlock",
"text": "Продукт",
"isSubtle": true
},
{
"type": "TextBlock",
"size": "extraLarge",
"color": "accent",
"text": me.value[i].fields.Good,
"spacing": "none"
},
{
"type": "TextBlock",
"text": "Дата: " + dateFormat(me.value[i].fields.ShipmentDateTime, 'dd-mm-yyyy'),
"spacing": "yes"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"text": " "
},
{
"type": "Image",
"url": "https://png.pngtree.com/svg/20170614/engine_oil_410031.png",
"size": "medium",
"spacing": "yes"
},
{
"type": "TextBlock",
"text": " ID: " + me.value[i].fields.id,
"value": me.value[i].fields.id
}
]
},
{
"type": "Column",
"width": 1,
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "right",
"text": "RUB",
"isSubtle": true
},
{
"type": "TextBlock",
"horizontalAlignment": "right",
"size": "extraLarge",
"color": "accent",
"text": me.value[i].fields.PricePerTon,
"spacing": "none"
},
{
"type": "Input.Toggle",
"title": "Приобрести лот",
"valueOn": "true",
"valueOff": "false",
"id": "buyGood",
"spacing": "yes"
}
]
}
]
}
tender.body.push(feed);
i++;
}
Then I combine these json.
This works well, but when you retrieve the data again, the data is doubled.
How can this be resolved?
Thanks in advance.
It looks like every time you create a new card, you are appending the JSON object you created in the while loop to your required JSON object. Consequently, the next time you try to create a new card, the data from the previous request is still stored in your required JSON object. To avoid this, create a copy of the required JSON Object and store it in a different variable before your while loop. You can use JSON.parse(JSON.stringify(obj)) to create a copy of a JSON Object.
Your code should look something like this:
// create a copy of the required JSON Object
// and store it in a new variable
const card = JSON.parse(JSON.stringify(tender));
var i = 0;
while (i < me['value'].length) {
let feed = {
"type": "ColumnSet",
"separator": true,
...
}
// push feed to `card` instead of `tender`
card.body.push(feed);
i++;
}
...
// send `card` to user instead of `tender`
await turnContext.sendActivity({
text: "Double Data Card",
attachments: [CardFactory.adaptiveCard(card)]
});

Get name per specified type in controller

I have an API that gets data from database. The sample data that I'm getting looks like this:
[
{
"Name": "Bar1",
"Type": "Bar",
},
{
"Name": "Pie1",
"Type": "Pie",
},
{
"Name": "Pie2",
"Type": "Pie",
},
{
"Name": "Line1",
"Type": "Line",
},
{
"Name": "Pie3",
"Type": "Pie",
},
]
I want to get all the names that belong to type=Pie and assign it on an $scope array and then put it on ng-repeat. How can I possibly do that?
The requirement can be easily fulfilled by ng-repeat and filter on view side, there is no need for additional operation in controller side.
Follow the below step:
In controller define like follows:
$scope.items = [{
"Name": "Bar1",
"Type": "Bar",
},
{
"Name": "Pie1",
"Type": "Pie",
},
{
"Name": "Pie2",
"Type": "Pie",
},
{
"Name": "Line1",
"Type": "Line",
},
{
"Name": "Pie3",
"Type": "Pie",
},
];
Please use the following in Html:
<div ng-controller = "YOUR_CONTROLLER">
<div ng-repeat="item in items | filter: { type: 'pie'}">
<div>
To get array of names only, check this. You can further assign this array to $scope variable and use in ng-repeat
First use filter to get filtered data and then select name from it.
let data = [
{
"Name": "Bar1",
"Type": "Bar",
},
{
"Name": "Pie1",
"Type": "Pie",
},
{
"Name": "Pie2",
"Type": "Pie",
},
{
"Name": "Line1",
"Type": "Line",
},
{
"Name": "Pie3",
"Type": "Pie",
},
]
let names = data.filter(d => d.Type === 'Pie').map(m => m.Name)
console.log(names)

Categories

Resources