How to form a new object from a json as key value pair in Typescript? - json

I have a below json array of objects which have data of currency list.
[
{
id:"AUD",
value:"1.55"
},
{
id:"BGN",
value:"1.95"
},
{
id:"USD",
value:"1.17"
},
{
id:"CAD",
value:"1.51"
},
{
id:"EUR",
value:"1"
},
{
id:"INR",
value:"80.00"
}
]
I want to form a new array of object say newList with only currency value for USD, CAD and EUR. I can manually find the position of the object(eg: say item[3].value will give rate for CAD)and update the new object but I want to look for key values and get the values instead of getting index positions manually. How to do the same?

I hope this is what you expect.
This is your original list.
const list = [{ id: "AUD", value: "1.55" }, { id: "BGN", value: "1.95" }, { id: "USD", value: "1.17" }, { id: "CAD", value: "1.51" }, { id: "EUR", value: "1" }, { id: "INR", value: "80.00" }];
And this is how you can extract the wanted objects by comparison with their id.
const newList = list.filter(el => this.matches(el.id));
console.log(newList);
This method does the comparison for you and returns true when id matches. You can dynamically remove or add currencies.
private matches(id: string): boolean {
let match: boolean = false;
switch (id) {
case 'AUD':
match = true;
break;
case 'USD':
match = true;
break;
case 'EUR':
match = true;
break;
default:
match = false;
break;
}
return match;
}

Related

JSON array item validation

I'd like to have tooling to perform certain validations on JSON. Explanation with examples:
Given JSON fragment:
{
"optionsMinValue": 0
"optionsMaxValue": 56
"options": [
{
"name": "name1",
"value": 0
},
{
"name": "name2",
"value": 1
},
{
"name": "name3",
"value": 56
}
]
}
Validation examples:
Given the fragment above, the validation of optionsMaxValue should
pass.
Given the fragment above, if optionsMaxValue is changed to 55, then
the validation should fail.
Added bonus validation:
Check whether an item is included in the options array for every integer between optionsMinValue and optionsMaxValue. In other words, in the given fragment the array should contain 57 items with an item for each value from 0 to 56.
Existing tooling:
Does tooling exist that can be used relatively easily to perform these sorts of checks?
First thought is that something like json-schema validation could be done. It has been a few years since I looked at that as an option, so my hope is that tooling has emerged that is a homerun on this.
Ajv JSON schema validator - github link
const schema = {
type: "object",
properties: {
name: {type: "string"},
value: {type: "number", minimum: 0, maximum: 55},
},
required: ["name", "value"],
additionalProperties: false,
}
const option = {
"name": "name1",
"value": 0
},
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.4.0/ajv.min.js"></script>
Joi package is best for these kind of validations
following Joi schema can be used to solve your requirement
Joi.object({
optionsMinValue: Joi.number().min(0).max(30).required(),
optionsMaxValue: Joi.number().min(56).max(100).required(),
options: Joi.array().items(
Joi.object({
name: Joi.string().required(),
value: Joi.number().min(0).max(56).required(),
})
),
});
Following is a sample code that works for your scenario
const inputData = {
optionsMinValue: 0,
optionsMaxValue: 56,
options: [
{
name: "name1",
value: 0,
},
{
name: "name2",
value: 1,
},
{
name: "name3",
value: 56,
},
],
};
const Joi = joi; // for node.js use - const Joi = require("joi");
// Schema for validation
const schema = Joi.object({
optionsMinValue: Joi.number().min(0).max(30).required(),
optionsMaxValue: Joi.number().min(56).max(100).required(),
options: Joi.array().items(
Joi.object({
name: Joi.string().required(),
value: Joi.number().min(0).max(56).required(),
})
),
});
const runValidation = (schema, inputData) => {
const validationResult = Joi.compile(schema)
.prefs({ errors: { label: "key" }, abortEarly: false })
.validate(inputData);
if (validationResult.error) {
// Validation failed
console.log("Error, validation failed");
// Set error message to string
const errorMessage = validationResult.error.details
.map((details) => details.message)
.join(", ");
console.log("failure reason - ", errorMessage);
return;
}
console.log("validation passed");
};
runValidation(schema, inputData);
<script src="https://cdn.jsdelivr.net/npm/joi#17.6.0/dist/joi-browser.min.js"></script>
Even if you use an existing tool, you should write validation rules for that tool. Since you are not an expert in any of these tools, it may be easier to write a few lines of code in your preferred language. For example, in JavaScript it might look like this:
function validateJson(jsonToValidate, maxValue = 56) {
if (jsonToValidate.optionsMaxValue !== maxValue) {
console.log("Failure on optionsMaxValue.");
return false;
}
if (jsonToValidate.options.length !== maxValue+1) {
console.log("Incorrect number of items.");
return false;
}
let values = jsonToValidate.options.map(a => a.value).sort();
if (values[0] !== 0 || values[maxValue] !== maxValue) {
console.log("Values out of desired sequence.");
return false;
}
let sum = values.reduce((a, b) => a + b, 0);
if (sum !== maxValue * (maxValue + 1) / 2) {
console.log("Values out of desired sequence.");
return false;
}
console.log("Validation PASSED.");
return true;
}
Let's try with truncated json object:
let jsonSample = {
"optionsMinValue": 0,
"optionsMaxValue": 2,
"options": [{
"name": "name1",
"value": 0
},
{
"name": "name2",
"value": 1
},
{
"name": "name3",
"value": 2
}
]
};
function validateJson(jsonToValidate, maxValue = 56) {
if (jsonToValidate.optionsMaxValue !== maxValue) {
console.log("Failure on optionsMaxValue.");
return false;
}
if (jsonToValidate.options.length !== maxValue+1) {
console.log("Incorrect number of items.");
return false;
}
let values = jsonToValidate.options.map(a => a.value).sort();
if (values[0] !== 0 || values[maxValue] !== maxValue) {
console.log("Values out of desired sequence.");
return false;
}
let sum = values.reduce((a, b) => a + b, 0);
if (sum !== maxValue * (maxValue + 1) / 2) {
console.log("Values out of desired sequence.");
return false;
}
console.log("Validation PASSED.");
return true;
}
validateJson(jsonSample, 2);

TypeScript: find values of certain keys in JSON

I have a JSON that contains a lot of data, here's an example of it:
{
"type":"doc",
"content":[
{
"type":"paragraph",
"content":[
{
"text":"this is a simple page, about a simple umbrella.",
"type":"text"
}
]
},
{
"type":"paragraph",
"content":[
{
"text":"you can use this text to find the umbrella page.",
"type":"text"
}
]
},
{
"type":"paragraph",
"content":[
{
"text":"do you like it?",
"type":"text"
}
]
}
}
I want to extract the value of text key, no matter where the key is located. I'm trying to go over the keys using Object.keys but it only returns the top-level keys:
for (let x of Object.keys(someJson)) {
console.log(x);
}
How can I find all the values of text in this JSON, no matter where in the JSON it is?
You can use JSON.stringify trick, you can intercept all keys from it
function find(obj: object, key: string) {
const ret: any[] = [];
JSON.stringify(obj, (_, nested) => {
if (nested && nested[key]) {
ret.push(nested[key]);
}
return nested;
});
return ret;
};
...
const o = {
key: '123',
a: {
key: 'hello',
b: [
{
c: {
key: 123,
},
},
],
},
};
it('123', () => {
console.log(JSON.stringify(find(o, 'key'))); // ["123","hello",123]
});
if you want for generic JSON just call this function and pass your object :
function printText(obj){
if(Array.isArray(obj)){
for(const o of obj){
printText(o);
}
}else if(typeof obj === "object"){
if (obj){
for(const o of Object.keys(obj)){
if(o==="text"){
console.log(obj.text);
}else{
printText(obj[o]);
}
}
}
}
}

Convert Form Data Array Object to JSON [duplicate]

This question already has answers here:
Convert JS object to JSON string
(23 answers)
Closed 1 year ago.
I'm trying to convert a form data object to JSON
var dataFormItin = $("#formitinerary").serializeArray();
result
itinerary: {
'itinerary[0][date]': undefined,
'itinerary[0][title]': 'Day 1 to Colombo',
'itinerary[0][destinationId]': '5ff3b8d7f0f3bf04b8141362',
'itinerary[0][program]': 'asd',
'itinerary[0][transfer_duration]': '2 hours'
}
and i want to make it like
itinerary : [
{ date : ..., title :...},
{ date : ..., title :...}
]
Maybe, it will be solved your problem
// 1. Example Data
const serializeArray = [
{ name: "itinerary[0][date]", value: "" },
{ name: "itinerary[0][title]", value: "Day 1 to Colombo" },
{ name: "itinerary[0][destinationId]", value: "5ff3b8d7f0f3bf04b8141362" },
{ name: "itinerary[0][program]", value: "asd" },
{ name: "itinerary[1][date]", value: "" },
{ name: "itinerary[1][title]", value: "Day 1 to Colombo" },
{ name: "itinerary[1][destinationId]", value: "5ff3b8d7f0f3bf04b8141362" },
{ name: "itinerary[1][program]", value: "asd" },
]
// 2. Define object key here
const arrayOfKey = ['date', 'title', 'destinationId', 'program']
// 3. Create empty array object
const arrayObject = []
// 4. Transform Serialize Array into Array Object
for(i = 0; i < serializeArray.length / arrayOfKey.length; i++ ){
const newObject = {}
for(const key of arrayOfKey){
newObject[key] = (serializeArray.find(data => data.name == `itinerary[${i}][${key}]`)).value
}
arrayObject.push(newObject)
}
// 5. Show the result
console.log(arrayObject)
/**
* [
{
date: '',
title: 'Day 1 to Colombo',
destinationId: '5ff3b8d7f0f3bf04b8141362',
program: 'asd'
},
{
date: '',
title: 'Day 1 to Colombo',
destinationId: '5ff3b8d7f0f3bf04b8141362',
program: 'asd'
}
]
*/

Kendo UI Grid Filtering column with multiple values

I have been using filters to successfully search on my KendoUI grids. However a new application has some fields that are multi-valued and my filtering doesn't work - it actually just seems to spin forever.
An example of a multi-value field:
field : "rspPersons",
title : "Responsible Persons",
type : "Text",
template: "# var t=rspPersons.join(', ');data.tagsString=t; # #=t #"
An example of my filter:
orfilter.filters.push( {
field : "chgDescription",
operator : "contains",
value : v1
},
orfilter.filters.push( {
field : "rspPersons",
operator : "contains",
value : v1
}
The second filter will make the entire search break down. If I take it out, then the search/filter works just fine.
So how can I filter/search on multi-value fields?
You'll need to push multiple filter criteria into filter array and assign it to the of Grid's datasource. Here's how I have done.
function onChange() {
var filter = { logic: "or", filters: [] };
// values is an array containing values to be searched
var values = this.value();
$.each(values, function (i, v) {
filter.filters.push({ field: "column_name", operator: "eq", value: v
});
});
var dataSource = $("#searchgrid").data("kendoGrid").dataSource;
dataSource.filter(filter);
}
You should set the logic option similar to the following.
filter({
logic: "or",
filters: [{
field: "LastName",
operator: "contains",
value: value
},
{
field: "FirstName",
operator: "contains",
value: value
}]
})
I create a seperate search textbox and then done the script like this it work's for me..
$("#search").keyup(function () {
var selecteditem = $('#search').val();
var kgrid = $("#gridName").data("kendoGrid");
selecteditem = selecteditem.toUpperCase();
var selectedArray = selecteditem.split(" ");
if (selecteditem) {
var orfilter = { logic: "or", filters: [] };
var andfilter = { logic: "and", filters: [] };
$.each(selectedArray, function (i, v) {
if (v.trim() == "") {
}
else {
$.each(selectedArray, function (i, v1) {
if (v1.trim() == "") {
}
else {
orfilter.filters.push({ field: "GridColumnFields", operator: "contains", value: v1 },
{ field: "LastName", operator: "contains", value: v1 },
{ field: "FirstName", operator: "contains", value: v1 },
{ field: "GridColumnFields", operator: "contains", value: v1 },
{ field: "GridColumnFields", operator: "contains", value: v1 }
);
andfilter.filters.push(orfilter);
orfilter = { logic: "or", filters: [] };
}
});
}
});
kgrid.dataSource.filter(andfilter);
}
else {
kgrid.dataSource.filter({});
}
});
You can define the add columns that you needed in search filter
you can create the textbox for this in html
<input type="text" id="search" name="search" />

ImmutableJS: Convert List to indexed Map

This question is about Immutable.js library.
I have a List<T>, where T is {name: string, id: number}. I want to convert it to Map<number, T>, with id of T to the keys. Using standard method toMap gives me a Map with sequential indexes, and there is no way to hook there. And no method like indexBy or other. how to do that?
You can do it with a reducer like this:
function indexBy(iterable, searchKey) {
return iterable.reduce(
(lookup, item) => lookup.set(item.get(searchKey), item),
Immutable.Map()
);
}
var things = Immutable.fromJS([
{id: 'id-1', lol: 'abc'},
{id: 'id-2', lol: 'def'},
{id: 'id-3', lol: 'jkl'}
]);
var thingsLookup = indexBy(things, 'id');
thingsLookup.toJS() === {
"id-1": { "id": "id-1", "lol": "abc" },
"id-2": { "id": "id-2", "lol": "def" },
"id-3": { "id": "id-3", "lol": "jkl" }
};