Nodejs - retrieve value from nested and non-nested json - javascript

I am passing json and a key to below function to retrieve its value. The key can be like abc.cde.def nad it can also be like fgh only.
If the keys contain . then it is a nested json and values has to be retrieved accordingly which is happening correctly but if it is a plain json having no nest then it is not working. Printing the length of keysData (in case the key is like fgh) it prints 3 where it should print 1.
function getValueFromJson(jsonInput,keyInput) {
if(keyInput.includes('.')){
var keysData = keyInput.split('.');
}
else {
keysData = keyInput.toString()
}
var jsonHierarchy = jsonInput;
if(parseInt(keysData.length) === parseInt('1')){
console.log(jsonHierarchy)
console.log(keysData )
console.log(jsonHierarchy[keysData ])
jsonHierarchy = jsonHierarchy[keysData ];
}
return jsonHierarchy;
};
Can anyone please help how can I handle this ?

you dont need to check for if(keyInput.includes('.'))
just do keyInput.split('.')
//for Ex.
'abc.defg'.split('.') // result ['abc', 'defg']
'abc'.split('.') // result ['abc']
and also
if(parseInt(keysData.length) === parseInt('1'))
//can be used as
if(keysData.length === 1)
and your complete function should be
function getValueFromJson(jsonInput,keyInput) {
var keysData = keyInput.split('.');
var jsonHierarchy = jsonInput;
keysData.forEach(function(d) {
if(jsonHierarchy)
jsonHierarchy = jsonHierarchy[d];
})
return jsonHierarchy;
};
var jsonData = {
'abc': {
'def': {
'gh': 'value1'
},
'xyz': 'value2'
}
};
function getValueFromJson(jsonInput, keyInput) {
var keysData = keyInput.split('.');
var jsonHierarchy = jsonInput;
keysData.forEach(function(d) {
if (jsonHierarchy)
jsonHierarchy = jsonHierarchy[d];
})
return jsonHierarchy;
};
function get() {
var val = document.getElementById('key').value;
if (val)
console.log(getValueFromJson(jsonData, val));
};
<input id="key" />
<button onclick="get()">Get Value</button>

Convert your string to an array, then your length with show properly.
var keysData = keyInput.split('.')

Related

How to overwrite a json object?

I have json object with a key named favorite, it has a value of true, when the button is pressed I want to overwrite the value of the favorite key to false and vica versa.
This is what`s inside the json object:
allPlaces: "[{"title":"Test1 ","description":"Test 2","category":"restaurant","favourite":false}]"
function favourite(element) {
var allPlaces = JSON.parse(localStorage.getItem("allPlaces"));
var placeIndex = element.getAttribute("data");
places = {allPlaces}
if (allPlaces["favourite"] == true) {
places.favourite[placeIndex] = false;
element.querySelector('ion-icon').setAttribute('name', 'star-outline');
} else {
console.log("working");
places.favourite[placeIndex] = true;
element.style.color = '#FFE234';
element.querySelector('ion-icon').setAttribute('name', 'star');
}
localStorage.setItem("allPlaces", JSON.stringify(places));
}
allPlaces is an array (in this case it has 1 item) so therefore in order to change the property of an object inside it you have to give it an index like so allPlaces[0].favorite = true
I added some code as a reference
const allPlaces = '[{"title":"Test1 ","description":"Test 2","category":"restaurant","favourite":false}]';
const places = JSON.parse(allPlaces);
places[0].favorite = true;
console.log(places[0]);

Javascript - Split and return array in multiple arrays or string

I have a json like this:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}
... and I dynamically fetch the values and create a variable this:
var existingParams = [
"name",
"updated"].filter(field => getBody.search[field]);
var sqlVal = existingParams.map(field => {
if (field === 'name') {
function getValues(item, index) {
var getVal = [item.tag];
return "%" + getVal + "%";
}
console.log(name.map(getValues));
return name.map(getValues);
} else {
return getBody.search[field];
}
})
For the above example I get for sqlVal:
console.log(sqlVal);
[ [ '%Peter%' ], '2018-11-07' ]
... which is fine.
BUT, if I have two values:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}}
... I'm getting this structure:
[ [ '%Peter%', '%Jack%' ], '2018-11-07' ]
... but what I need is sth like:
[ '%Peter%', '%Jack%', '2018-11-07' ]
... or:
[ ['%Peter%'], ['%Jack%'], '2018-11-07' ]
And in case of further e.g. 3 names:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}
... I need sth like:
[ '%Peter%', '%Jack%', '%Maria%', '2018-11-07' ]
... or:
[ ['%Peter%'], ['%Jack%'], ['%Maria%'], '2018-11-07' ]
... and so on
How do I need to adjust the above query to get this?
If I understand your question correctly, then this problem can be solved via the Array#reduce() method.
The general idea with this approach is to transform your input object to an array - the reduce operation can be used to do this, with the special-case rule of "flattening" the nested value on the name key into the final result:
var input = {"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}}
var result = Object
.entries(input.search)
.reduce(function(result, entry) {
const key = entry[0]
const value = entry[1]
if(key === 'name') {
// When the 'name' key is encountered, handle the value
// differently, by addting the items of this value array
// to the result
value.forEach(function(item) {
result.push('%' + item.tag + '%')
})
}
else {
// Append values for other keys directly to the result
result.push(value)
}
return result
}, [])
console.log(result )
You could simply use Object.values + reduce for something like this:
const json = { "search": { "updated": "2018-11-07", "name": [{ "tag": "Peter" }, { "tag": "Jack" }, { "tag": "Maria" }] } }
const result = Object.values(json.search).reduce((r,c) =>
(Array.isArray(c) ? r.push(...c.map(({tag}) => `%${tag}%`)) : r.push(c), r),[])
console.log(result)
If the order is important (names first then date) you could use reverse:
const json = { "search": { "updated": "2018-11-07", "name": [{ "tag": "Peter" }, { "tag": "Jack" }, { "tag": "Maria" }] } }
const result = Object.values(json.search).reverse().reduce((r,c) =>
(Array.isArray(c) ? r.push(...c.map(({tag}) => `%${tag}%`)) : r.push(c), r),[])
console.log(result)
First of all you did not provide a Minimal, Complete, and Verifiable example so it is quite hard for me to figure out where you are running into issues. For example, you are referencing existingParam but nowhere are they defined. This is key to understanding the problem because all of the code that you posted is heavily invested in the values and format of this value.
Second, how are you parsing the JSON? With the standard JSON#parse function you would get back an object with the same structure as your provided JSON. However, you are either not using this or you are mutating the object after it was parsed into a new format. Either way, the object that JSON#parse returns for the provided JSON is not an array and therefor you cannot use Array#map on it.
For the sake of being productive though I am going to try and explain how to do things.
JSON:
let data1 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}',
data2 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}} ',
data3 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}';
Now that we have our JSON data we need to parse it and store it as a JSON object. To do so I am going to create a function; this way the data can be passed to the same function and handled the same way but the implementation will stay the same. Also, since we are only looking at the values in the search property we are going to go ahead and jump right into it.
Parse the JSON:
function parseResponse (response) {
let parsedResponse = JSON.parse(response);
parsedResponse = parsedResponse['search'];
}
Now that we have our function that takes our response and parses it we can then begin to sort through it to find and isolate the parts that we want. In this case we will add some code to loop through our properties and find the updated and name properties.
function parseResponse (response) {
let parsedResponse = JSON.parse(response);
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
// do stuff with 'updated'
}
if (prop === 'name') {
// do stuff with 'name'
}
}
}
Because we want to return a result we are going to add a variable updated and names which will hold the values that we pull out of the string until we are ready to return them. Now that we have our loop and our temporary variables we can go ahead and pull the updated value out of our data and place it in the updated variable.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
// do stuff with 'name'
}
}
}
With our updated value squared away we can jump into our names. Since you listed the format ['%name%', '%name%', '%name%'] first I am going to go ahead and show you how to do it this way. Here we are going to grab the property name, iterate through the names, grab the tag property, and then add the %s before pushing it to our names temporary variable.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
}
With everything in place all that is left is to assemble the result. To do so we are going to flatten the array of names, add them to the array, and then add the updated value to the end before returning it. To flatten the array we are going to use the spread operator.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
return [...names, updated];
}
With all of that set we can go ahead and call parseResponse() with data1, data2, or data3 and get back a response that looks like so:
let data1 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}',
data2 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}} ',
data3 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}';
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
return [...names, updated];
}
console.log(parseResponse(data1));
console.log(parseResponse(data2));
console.log(parseResponse(data3));
Spread operator can be used to flatten the result :
var obj = {"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}
var arr = [...obj.search.name.map(n => `%${n.tag}%`), obj.search.updated]
console.log( arr )
Another alternative could be to extract during parsing :
var arr = [], json = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}'
JSON.parse(json, (k, v) => v.trim && arr.push(k === 'tag' ? `%${v}%` : v))
console.log( arr )

javascript adding object to an array

this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.journeyIds.map((id)=>{
this.journeyDetails.push({
id: this.el("#" + id).inputValue
});
});
I want array like [{Source : "LMP"}, {Destination : "LKO"}];
i.e I want to make Id as key in object
thank you!
It seems that you want the id as key of an object. Use [] around the id
this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.journeyIds.map((id) => {
this.journeyDetails.push({[id] :
this.el("#"+id).inputValue});
});
I don't have the function this.el() so it's an array here, you could just replace it with the function call (this.el["#"+id].inputValue => this.el("#"+id).inputValue
this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.el = {
"#source": {inputValue: "foo"},
"#destination": {inputValue: "bar"}
}
this.journeyIds.forEach((id) => {
let temp = {};
temp[id] = this.el["#"+id].inputValue;
this.journeyDetails.push(temp);
});
console.log(this.journeyDetails)

IndexedDB: How to use multiple indexes along with 'multiEntry: true'

If I got these data in an indexedDB:
{
name:"Ray",
age:20,
tags:["apple","banana","beer"]
}
{
name:"Scott",
age:25,
tags:["beer"]
}
{
name:"Marc",
age:28,
tags:["mongo","jenkins"]
}
Then I want to find persons who have tag 'beer' and ordered the result by age, what should I do?
According to this article http://www.raymondcamden.com/2012/8/10/Searching-for-array-elements-in-IndexedDB, 'multiEntry: true' should be applied to query array field, but it'll show an error if I use it with multiple indexes. So what query can achieve the goal? Thanks.
In onupgradeneeded callback function:
store.createIndex('tagsIndex','tags', {multiEntry: true});
In your query section, do
var tx = db.transaction('store');
var tagsIndex = tx.objectStore('store').index('tagsIndex');
var beerQuery = tagsIndex.openCursor(IDBKeyRange.only('beer'));
var people = [];
beerQuery.onsuccess = function(event) {
var cursor = this.result;
if(!cursor) return;
people.push(cursor.value);
cursor.continue();
};
tx.oncomplete = function() {
onGetPeopleWhoLikeBeerSortedByAgeAsc(people.sort(function(p1, p2) {
if(p1.age > p2.age) return -1;
if(p1.age == p2.age) return 0;
return 1;
}));
};

how to change attribute text of json in jquery?

I am trying to change the property name /attr name of my json object.I try like that but nothing will change.I need to make json object after seen the input json and convert it like outjson
function changeData(data){
var title;
for(var i = 0; i < data.length; i++){
if(data[i].hasOwnProperty("displayName")){
data[i]["label"] = data[i]["displayName"];
delete data[i]["displayName"];
}
if(data[i].hasOwnProperty("displayDetail")){
data[i]["title"] = data[i]["displayDetail"];
delete data[i]["displayDetail"];
}
if(data[i].hasOwnProperty("inputType")){
if(data[i]["inputType"]=="NUMBER"){
data[i]["type"]="number"
}else if(data[i]["inputType"]=="TEXT"){
data[i]["type"]="text"
}else if(data[i]["inputType"]=="SWTICH"){
data[i]["type"]="select"
}
delete data[i]["inputType"];
}
}
console.log(data);
}
Try this - it's possibe to remove the if selection for inputType by creating a tiny lookup table from original value to new value:
function changeData(data) {
var map = { NUMBER: "number", TEXT: "text", SWITCH: "select" };
// data is an object - use for .. in to enumerate
for (var key in data.input) {
var e = data.input[key]; // alias for efficient structure dereferencing
e.label = e.displayName;
e.title = e.displayDetail;
e.type = map[e.inputType];
delete e.displayName;
delete e.displayDetail;
delete e.inputType;
}
};
There's really no need for the hasOwnProperty test these days - only use it if you think there's any risk that someone unsafely added to Object.prototype. jQuery manages without it quite happily, other modern code should do to.
If the mapping of field names was any longer I'd consider using another mapping table with another loop to remove the hard coded copy/delete pairs.
i have a nice Recursive function for that:
usage:
// replace list
var replacedObj = replaceAttrName(sourceObject, {foo: 'foooo', bar: 'baaar'});
so in your case you can easily do:
var newObj = replaceAttrName(json, {displayDetail: 'title', displayName: 'label', inputType: 'type'});
demo: http://jsfiddle.net/h1u0kq67/15/
the function is that:
function replaceAttrName(sourceObj, replaceList, destObj) {
destObj = destObj || {};
for(var prop in sourceObj) {
if(sourceObj.hasOwnProperty(prop)) {
if(typeof sourceObj[prop] === 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[strName]);
} else if(!replaceList[prop]) {
destObj[prop] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[prop]);
}
} else if (typeof sourceObj[prop] != 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = sourceObj[prop];
} else if(!replaceList[prop]) {
destObj[prop] = sourceObj[prop];
}
}
}
}
return destObj;
}
If I am getting you right, you just want substitutions:
displayDetail => title
displayName => label
inputType => type.
I came up with the follwoing:
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type"));
}
Here is the Fiddle to play with.
Edit: I forgot replacements for "NUMBER", "TEXT" and "SWITCH".
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type").replace(/TEXT/g, "text").replace(/NUMBER/g, "number").replace(/SWITCH/g, "switch"));
}

Categories

Resources