Remove $ from JSON Object - possible? - javascript

I have an object that looks like this:
{
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
Is it possible to remove the $ somehow so the object looks like this:
{
alphabet: {
id: '11',
href: 'abc'
mydata: [[Object]],
status: ['22']
}
}
I'm new to JavaScript and Node JS, and struggling to figure this out. I tried delete object.$; but it does not do anything. I'm pretty sure that I misunderstood this function.
Any help will be appreciated!

Clone $ and use object.assign to merge clone and original object
var obj = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [''],
status: ['22']
}
};
var clone = obj.alphabet["$"];
delete obj.alphabet["$"];
Object.assign(obj,clone);
console.log(obj);

You mean put $ object into the root object.
If the key name is always $, you could get the key-value in $ object as below:
let alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
for (let key in alphabet['$']) {
alphabet[key] = alphabet['$'][key]
// maybe you should consider the duplicate key.
}

Here is a function that will loop through the properties of a property in an object and flatten it.
function flattenProp(obj, prop) {
var key;
for(key in obj[prop]) {
obj[key] = obj[prop][key];
}
delete obj[prop];
};
Below is an example of it being used.
var data = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
};
console.log(data);
flattenProp(data.alphabet, '$');
console.log(data);
function flattenProp(obj, prop) {
var key;
for(key in obj[prop]) {
obj[key] = obj[prop][key];
}
delete obj[prop];
};

This solution is quite simple -
var obj = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
var temp = obj.alphabet.$
//copies the internal object to main one
for(var i=0;i<Object.keys(temp).length;i++) {
obj.Object.keys(temp)[0] = temp[Object.keys(temp)[0]];
}
delete obj.alphabet.$ //remove the old object from it

Of course it is possible.
Assuming your data variable (JSON) is named "data":
var data = JSON.parse("your json string");
so data looks like this:
var data = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
We just need to iterate over data.alphabet.$, store all its properties to its parent (data.alphabet) and then delete data.alphabet.$:
for(var propname in data.alphabet["$"]) {
var propvalue = data.alphabet["$"][propname];
data.alphabet[propname] = propvalue;
}
delete data.alphabet.$;
here's a snippet:
var data = JSON.parse(`{
"alphabet": {
"$": {
"id": "11",
"href": "abc"
},
"mydata": {},
"status": ["22"]
}
}`)
for(var propname in data.alphabet["$"]) {
var propvalue = data.alphabet["$"][propname];
data.alphabet[propname] = propvalue;
}
delete data.alphabet.$;
document.body.innerHTML = `<pre>${JSON.stringify(data, null, 4)}</pre>`

Related

Deep replace a value knowing the value of an attribute within the object we must inject value in

We have a deeply nested structure which varies each time we run the app.
{
some: {
complex: {
unknown: {
structure: {
fields: [
{ name: "group1", other: "data", currentValue: "" },
{ name: "group2", other: "another data", currentValue: "" },
]
}
}
}
}
}
We must inject, in this structure, proper value. We receive for example
{
group1: 'the proper value'
}
And we must replace the value in the proper group to obtain:
{
some: {
complex: {
unknown: {
structure: {
fields: [
{ name: "group1", other: "data", currentValue: "the proper value" },
{ name: "group2", other: "another data", currentValue: "" },
]
}
}
}
}
}
We tried to use lodash mergeWith but since we cannot know where exactly is the value we must inject and we only know the value of of of the key of the object we must inject the value in, we didn't manage to get this working.
Have a recursive function going through the object and mutating it depending on the value of what you seek.
const obj = {
some: {
complex: {
unknown: {
structure: {
fields: [{
name: 'group1',
other: 'data',
currentValue: '',
},
{
name: 'group2',
other: 'another data',
currentValue: '',
},
],
},
},
},
},
};
const toChange = {
group1: 'the proper value',
group2: 'the proper value 2',
};
// Recursive function that go replace
function lookAndReplace(config, ptr) {
// If we deal with an object look at it's keys
if (typeof ptr === 'object') {
Object.keys(ptr).forEach((x) => {
// If the keys is the one we was looking for check the value behind
if (x === config.keyToCheck) {
// We have found one occurence of what we wanted to replace
// replace the value and leave
if (ptr[x] === config.key) {
ptr[config.keyToReplace] = config.value;
}
return;
}
// Go see into the value behind the key for our data
lookAndReplace(config, ptr[x]);
});
}
// If we are dealing with an array, look for the keys
// inside each of the elements
if (ptr instanceof Array) {
ptr.forEach(x => lookAndReplace(config, x));
}
}
// For each group we look for, go and replace
Object.keys(toChange).forEach(x => lookAndReplace({
key: x,
value: toChange[x],
keyToCheck: 'name',
keyToReplace: 'currentValue',
}, obj));
console.log(obj);
/!\ Important this soluce also work with nested arrays
const obj = {
some: {
complex: {
unknown: {
structure: {
// fields is an array of array
fields: [
[{
name: 'group1',
other: 'data',
currentValue: '',
}],
[{
name: 'group2',
other: 'another data',
currentValue: '',
}],
],
},
},
},
},
};
const toChange = {
group1: 'the proper value',
group2: 'the proper value 2',
};
// Recursive function that go replace
function lookAndReplace(config, ptr) {
// If we deal with an object look at it's keys
if (typeof ptr === 'object') {
Object.keys(ptr).forEach((x) => {
// If the keys is the one we was looking for check the value behind
if (x === config.keyToCheck) {
// We have found one occurence of what we wanted to replace
// replace the value and leave
if (ptr[x] === config.key) {
ptr[config.keyToReplace] = config.value;
}
return;
}
// Go see into the value behind the key for our data
lookAndReplace(config, ptr[x]);
});
}
// If we are dealing with an array, look for the keys
// inside each of the elements
if (ptr instanceof Array) {
ptr.forEach(x => lookAndReplace(config, x));
}
}
// For each group we look for, go and replace
Object.keys(toChange).forEach(x => lookAndReplace({
key: x,
value: toChange[x],
keyToCheck: 'name',
keyToReplace: 'currentValue',
}, obj));
console.log(obj);
const obj = {
some: {
complex: {
unknown: {
structure: {
fields: [{
name: "group1",
other: "data",
currentValue: ""
},
{
name: "group2",
other: "another data",
currentValue: ""
},
]
}
}
}
}
};
const toChange = {
group1: 'the proper value',
group2: 'the proper value 2',
};
// Recursive function that go replace
function lookAndReplace({
key,
value,
keyToCheck,
keyToReplace,
}, ptr) {
// If we deal with an object
if (typeof ptr === 'object') {
Object.keys(ptr).forEach((x) => {
if (x === keyToCheck) {
// We have found one
if (ptr[x] === key) {
ptr[keyToReplace] = value;
}
} else {
lookAndReplace({
key,
value,
keyToCheck,
keyToReplace,
}, ptr[x]);
}
});
}
if (ptr instanceof Array) {
ptr.forEach(x => lookAndReplace({
key,
value,
keyToCheck,
keyToReplace,
}, x));
}
}
// For each group we look for, go and replace
Object.keys(toChange).forEach(x => lookAndReplace({
key: x,
value: toChange[x],
keyToCheck: 'name',
keyToReplace: 'currentValue',
}, obj));
console.log(obj);
A solution could be to use a recursive function like this:
object={
some: {
complex: {
unknown: {
structure: {
fields: [
{ name: "group1", other: "data", currentValue: "" },
{ name: "group2", other: "another data", currentValue: "" },
]
}
}
}
}
};
newValue={
group1: 'the proper value'
};
var inserted=false;
function search(data, newData){
if(inserted) return;
for(key in data){
if(data[key]==Object.keys(newData)[0]){
data["currentValue"]=newData[Object.keys(newData)[0]];
inserted=true;
return;
}else
search(data[key], newData);
}
}
search(object, newValue);
console.log(object);
You could do a recursive search and replace...
let theObj = {
some: {
complex: {
unknown: {
structure: {
fields: [
{ name: "group1", other: "data", currentValue: "" },
{ name: "group2", other: "another data", currentValue: "" },
]
}
}
}
}
}
function updateObj(obj, replacement) {
if(Array.isArray(obj)) {
let key = Object.keys(replacement)[0]
let itm = obj.find(i => i.name == key)
itm.data = replacement[key]
} else if(typeof obj == 'object') {
for(let i in obj) {
updateObj(obj[i], replacement)
}
}
}
updateObj(theObj, { group1: 'the proper value' })
console.log(theObj)

javascript filter by object key and return value of nested object key

I want to return the value of a key for one of the elements inside the object using a condition:
const raw = {
item1: { name: 'sdfd1', otherStuff: { book:'sdfd11' } },
item2: { name: 'sdfd2', otherStuff: { book:'sdfd22' } },
item3: { name: 'sdfd3', otherStuff: { book:'sdfd33' } }
};
var anotherOne = {
country1 : { city: 'one', item: 'item3'},
country2 : { city: 'two', item: 'item4'}
}
var searchTerm = anotherOne.country1.item; // item3
var secondTerm = someUser.otherInfo // 'otherStuff'
var result = Object.keys(raw)
.filter(key => {
if (key === searchTerm){
return raw[searchTerm][secondTerm].book
}})
console.log('result:' result); // sdfd33
Basically, i want to look for the searchTerm in the keys of the object raw, and return the value for the book key. In this example, it should return sdfd33.
My attempt is returning nothing.
updated:
updated the question.
Use square bracket [] while accessing a object key through a variable.
Hopefully the filter & Object.keys will not be required in this case
const raw = {
item1: {
name: 'sdfd1',
book: 'sdfd11'
},
item2: {
name: 'sdfd2',
book: 'sdfd22'
},
item3: {
name: 'sdfd3',
book: 'sdfd33'
}
};
var searchTerm = 'item3';
//using square bracket when acceing key using variable
var result = raw[searchTerm].book
console.log(result);
You can simply return the value like :
var result = raw.item3.book;
console.log(result);
result should be sdfd33

Filter a dom object of input tags

I am building an object from a form that is currently rendered server side. I collect all the check boxes displayed in the image below and I am trying to sort them in a way that all the check boxes under each step (1, 2, 3 etc) is a single object based on the property parentNode.
Currently the document.querySelectorAll('.checkboxes') fetches all the checkboxes in following format.
var newObj = [
{
name: 'one',
parentNode: {
id: 'stepOne'
}
},
{
name: 'two',
parentNode: {
id: 'stepTwo'
}
},
{
name: 'three',
parentNode: {
id: 'stepOne'
}
},
]
The new object should be:
var newObj = {
stepOne: [
{
name: 'one',
parentNode: {
id: 'stepOne'
}
},
{
name: 'three',
parentNode: {
id: 'stepOne'
}
},
],
stepTwo: [
{
name: 'two',
parentNode: {
id: 'stepTwo'
}
},
]
}
Usually I do something like this:
let stepOne = function(step) {
return step.parentNode.getAttribute('id') === 'stepOne';
}
let stepTwo = function(step) {
return step.parentNode.getAttribute('id') === 'stepTwo';
}
let allTheStepOnes = fetchCheckBoxes.filter(stepOne);
But filter doesn't work on dom object and this seems inefficient as well.
Proper way of doing this is a forEach loop and using associative arrays like this:
let newObject = {};
originalObject.forEach((item)=>{
let step = item.parentNode.id
if (newObj[step] === undefined) {
newObj[step] = []
}
newObj[step].push(item)
})
Using reduce we can reduce your current array into the new structure.
return newObj.reduce(function(acc, item) {
If acc[item.parentNode.id] has been defined before, retrieve this. Otherwise set it to an empty array:
acc[item.parentNode.id] = (acc[item.parentNode.id] || [])
Add the item to the array and then return it:
acc[item.parentNode.id].push(item);
return acc;
We set the accumulator as {} to start with.
Snippet to show the workings.
var newObj = [{
name: 'one',
parentNode: {
id: 'stepOne'
}
}, {
name: 'two',
parentNode: {
id: 'stepTwo'
}
}, {
name: 'three',
parentNode: {
id: 'stepOne'
}
}, ];
var newOrder = function(prevList) {
return prevList.reduce(function(acc, item) {
acc[item.parentNode.id] = (acc[item.parentNode.id] || [])
acc[item.parentNode.id].push(item);
return acc;
}, {});
}
console.log(newOrder(newObj));
This function should do the trick
function mapObj(obj) {
var result = {};
for(var i = 0; i < obj.length; i++) {
var e = obj[i];
result[e.parentNode.id] = result[e.parentNode.id] || [];
result[e.parentNode.id].push(e);
}
return result;
}

Javascript get parent of item in array

I am trying to get the parent of a specific (referenced) object in an array.
Example:
var data = [
{
key: "value1"
children: [
{
key: "value2"
},
{
key: "value3"
children: [
{
key: "value3a"
},
{
key: "value3b"
}
]
}
]
},
{
key: "value4"
}
];
When some stuff happens, I get the following:
var clicked = {
key: "value3a"
}
In this case I know that value3a has been clicked, and it's databound with the data variable.
The question is, how do I easily get the parent of clicked? It should return the whole children-array of value3 which I want:
[
{
key: "value3a"
},
{
key: "value3b"
}
]
Note: currently I am using UnderscoreJS to find the object of my array. So maybe UnderscoreJS could help?
Just create a child-parent map so that you can look up what you need:
var map = {};
function recurse(arr, parent) {
if (!arr) return;
for (var i=0; i<arr.length; i++) { // use underscore here if you find it simpler
map[arr[i].key] = parent;
recurse(arr[i].children, arr[i]);
}
}
recurse(data, {key:"root", children:data});
Now, in your event handler you can trivially use that map to look up your siblings:
map[clicked.key].children
You could use a recursive reduce function.
// Given
var data = [
{
key: "value1",
children: [
{
key: "value2"
},
{
key: "value3",
children: [
{
key: "value3a"
},
{
key: "value3b"
}
]
}
]
},
{
key: "value4"
}
];
var clicked = {
key: "value3a"
};
We can define a recursive reduce function, and give it the parent
as the context.
var rec_reduce = function(memo, obj) {
if(obj.key == clicked.key) {
return this || memo;
}
return _.reduce(obj.children, rec_reduce, memo, obj.children) || memo;
};
// Now we can lookup the key in clicked with one line
_.reduce(data, rec_reduce, null, data);
// Returns [{key: "value3a"}, {key: "value3b"}]
Or, if you want to leverage underscore to make a map as suggested in the first answer, that is even simpler:
var map = {};
var rec_map = function(obj, i, parent) {
map[obj.key] = parent;
_.each(obj.children, rec_map);
};
_.each(data, rec_map);
// Now getting the parent list is just a look up in the map
map[clicked.key]
// Returns [{key: "value3a"}, {key: "value3b"}]

Dynamically drill down nested array of objects

How can I dynamically drill down my array of objects? Let me explain. Say I have this array of objects with subarrays:
var arrOfObjects = [
{
name: 'something',
subArray: [ {
name: 'nested something'
} ]
},
{
name: 'something else',
subArray: [ {
name: 'nested something else'
} ]
}];
and a reference to know which array in the hierarchy I need to modify
var referenceArr = [1,0];
How do I use this reference to generate the proper location in my data array, in this case, I would want to get to
arrOfObject[1]['subArray][0]['name'];
// 'subArray' and 'name' are always the same
The reference array could be any length, so
var referenceArr= [0];
indicates modifying:
arrOfObject[0]['name'];
Use this function:
function getValue(source, path){
var result = source;
while(path.length){
result = result[path.shift()];
if(path.length && !result.subArray)
throw new Error('Incorrect path!');
else if(path.length)
result = result.subArray;
else
result = result.name;
}
return result;
}
fiddle
Try this Check this jsfiddle
var arrOfObjects = [
{
name: 'something',
subArray: [ {
name: 'nested something'
} ]
},
{
name: 'something else',
subArray: [ {
name: 'nested something else'
} ]
}];
for(var i=0; i<arrOfObjects.length;i++){
alert(arrOfObjects[i].subArray[0].name)
}

Categories

Resources