Javascript: removing elements from Json by value - javascript

I need to remove elements from a json string returned by an AJAX call.
I'm not sure how to loop through the string and remove all elements where the value i NULL.
My json looks like this.
[
{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},
{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},
{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},
{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},
{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}
]
I thought I might do something like this for every key but i would prefer a generic function:
if(json[index].Strength == null){
json.splice(index,1);
}

You can parse json with JSON.parse method and then use filter() method on that array.
const json = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]'
const data = JSON.parse(json).filter(o => o.Strength != null)
console.log(data)
If you want to remove elements where some property has value of null you can use some method inside filter.
const json = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]'
const data = JSON.parse(json).filter(o => {
return !Object.keys(o).some(k => o[k] == null)
})
console.log(data)

Use filter:
const newJson = json.filter(item => item.Strength !== null)

If you prefer a generic function, Lodash is the best option.
PickBy picks up properties from an object, based on a Predicate.
Here predicate is Identity, which means, pickup non null properties from the object.
var jsonResponse = '[{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}]';
var responseArr = JSON.parse(jsonResponse);
// Only lines that matter
responseArr = _.map(responseArr, function(obj) {
return _.pickBy(obj, _.identity);
});
console.log("Array of Objects: ", responseArr);
console.log("JSON: ", JSON.stringify(responseArr));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
Put the above mentioned script tag just before closing tag of your html page.
So just loop through the whole array response using map, and apply PickBy on each object of the array, and you have yourself an array of sparse objects.

Try Array filter() method with ES6 Arrow function.
Demo
var jsonObj = [
{"ID":"27","Agility":"15","Balance":null,"Strength":"37","Physiology":"32"},
{"ID":"30","Agility":"27","Balance":null,"Strength":null,"Physiology":null},
{"ID":"34","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"36","Agility":null,"Balance":null,"Strength":null,"Physiology":null},
{"ID":"40","Agility":null,"Balance":"20","Strength":null,"Physiology":"34"},
{"ID":"42","Agility":null,"Balance":"16","Strength":null,"Physiology":null},
{"ID":"51","Agility":null,"Balance":null,"Strength":"39","Physiology":null}
];
var res = jsonObj.filter(elem => elem.Strength !== null);
console.log(res);

Related

JSON.stringify not printing all fields [duplicate]

I must be missing something here, but the following code (Fiddle) returns an empty string:
var test = new Array();
test['a'] = 'test';
test['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
What is the correct way of JSON'ing this array?
JavaScript arrays are designed to hold data with numeric indexes. You can add named properties to them because an array is a type of object (and this can be useful when you want to store metadata about an array which holds normal, ordered, numerically indexed data), but that isn't what they are designed for.
The JSON array data type cannot have named keys on an array.
When you pass a JavaScript array to JSON.stringify the named properties will be ignored.
If you want named properties, use an Object, not an Array.
const test = {}; // Object
test.a = 'test';
test.b = []; // Array
test.b.push('item');
test.b.push('item2');
test.b.push('item3');
test.b.item4 = "A value"; // Ignored by JSON.stringify
const json = JSON.stringify(test);
console.log(json);
Nice explanation and example above. I found this (JSON.stringify() array bizarreness with Prototype.js) to complete the answer. Some sites implements its own toJSON with JSONFilters, so delete it.
if(window.Prototype) {
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}
it works fine and the output of the test:
console.log(json);
Result:
"{"a":"test","b":["item","item2","item3"]}"
I posted a fix for this here
You can use this function to modify JSON.stringify to encode arrays, just post it near the beginning of your script (check the link above for more detail):
// Upgrade for JSON.stringify, updated to allow arrays
(function(){
// Convert array to object
var convArrToObj = function(array){
var thisEleObj = new Object();
if(typeof array == "object"){
for(var i in array){
var thisEle = convArrToObj(array[i]);
thisEleObj[i] = thisEle;
}
}else {
thisEleObj = array;
}
return thisEleObj;
};
var oldJSONStringify = JSON.stringify;
JSON.stringify = function(input){
if(oldJSONStringify(input) == '[]')
return oldJSONStringify(convArrToObj(input));
else
return oldJSONStringify(input);
};
})();
Another approach is the JSON.stringify() replacer function param. You can pass a 2nd arg to JSON.stringify() that has special handling for empty arrays as shown below.
const arr = new Array();
arr.answer = 42;
// {"hello":"world","arr":{"answer":42}}
JSON.stringify({ hello: 'world', arr }, function replacer(key, value) {
if (Array.isArray(value) && value.length === 0) {
return { ...value }; // Converts empty array with string properties into a POJO
}
return value;
});
Alternatively you can use like this
var test = new Array();
test[0]={};
test[0]['a'] = 'test';
test[1]={};
test[1]['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
Like this you JSON-ing a array.
Json has to have key-value pairs. Tho you can still have an array as the value part. Thus add a "key" of your chousing:
var json = JSON.stringify({whatver: test});

How I can filter a value corresponding to a specific key in a string?

In my JS code, i have string as
s = "{\"selector\":{\"owner\":\"tom\"}}"; // originally this is a query response
I want to extract the value of 'owner' which is tom in another variable, s1.
What would be the easiest way to do it?
To convert your data to an object use obj = JSON.parse(s)
Then obj.selector.owner Or
obj["selector"]["owner"] which is the recommended way to get JavaScript object values...
You are not selecting the right properties when accessing your response data. Also you do not need to use toString in JSON.parse. Because your response is already a string data.
You want to convert string data by using JSON.parse
Demo:
//Response # 1
let findOwner = "{\"selector\":{\"owner\":\"tom\"}}"
//Parse Data
let parseData = JSON.parse(findOwner)
console.log(parseData.selector.owner) //Tom
//Response # 2
let findOwner2 = "{\"response\":{\"colour\":\"black\",\"make\":\"Tesla\",\"model\":\"S\",\"owner\":\"Adriana\"}}"
//Parse Data
let parseData2 = JSON.parse(findOwner2)
console.log(parseData2.response.owner) //Adriana
You can use a function for this:
function get(path, obj) {
return path.split('.').reduce((acc, current) => acc && acc[current], obj)
}
const obj = "{\"selector\":{\"owner\":\"tom\"}}"
const parsed = JSON.parse(obj)
get('selector.owner', parsed) // return 'tom'

Push unique objects into array in JAVASCRIPT

I want to push object that only have unique id1 into array.
Example:
let array = [],
obj = {},
access = true
if(access){
obj['id1'] = 1
obj['id2'] = 2
if(array.indexOf(obj.id1) == -1){
array.push(obj)
}
}
console.log(array);
In the above example I am trying to add value to obj then push the obj into array. But obj.id1 need to be unique. The method I am using above doesn't work in my case.
Thank you
As Taplar says, indexOf will look for the first instance of the thing you pass in in the other array. This won't work because there are no instances of the ids in the array, directly anyway.
Use the find function, which allow you pass in a comparison function, so you can define what a match is.
let initial = [{id:1}, {id:2}, {id:1}];
let result = initial.reduce((acc, item) =>
{
if(!acc.find(other => item.id == other.id))
{
acc.push(item);
}
return acc;
}, []);
console.log(result);
Simplest solution . Lets say myObjArray have duplicate object use below es6 code to get unique array from that
// Creates an array of objects with unique "name" property values.
let uniqueObjArray = [
...new Map(myObjArray.map((item) => [item["name"], item])).values(), ]; console.log("uniqueObjArray", uniqueObjArray);
Refer here for more detail https://yagisanatode.com/2021/07/03/get-a-unique-list-of-objects-in-an-array-of-object-in-javascript/
I think you need to use findIndex and not indexOf.
Try replacing your if condition with the following:
array.findIndex((o)=>{ return o.id1 === obj.id1 }) === -1

Filter Array (with nested Objects) by dynamic props

I have an array of N objects. I would like to write a filter that filters using JSON.stringify based on multiple and dynamic properties.
But dynamic without static properties (like the code above)
Do you have any ideas?
return items.filter(item =>
JSON.stringify(item.prop1 && item.prop2 && ....)
.toLowerCase()
.includes(searchParam)
);
You're gonna have to write a function that transforms your object into a stripped down object with just the properties you want:
function getProperties(obj, propList) {
var newObj = {};
propList.forEach(prop => {
newObj[prop] = obj[prop];
});
return newObj;
}
And then your code will look like this:
var propList = ['id','name','date']; // just for example, put whatever properties you want in here
return items.filter(item =>
JSON.stringify(getProperties(item, propList))
.toLowerCase()
.includes(searchParam)
);
items.filter(item => ["prop1", "prop2"].some(key => item[key].toLowerCase() === searchParam))
Using JSON.stringify to turn the object into a searchable string is a bad idea as the keys are also included in the search and it will be way slower than just traversing the neeeed keys.

Query large JSON object for condition

I'm trying to parse a large JSON object for a specific condition
My current approach is to set up a recursive filter:
function filter(obj,fn,items){
//Initialise items array
if(items==undefined)
items = []
//Filter for specific child objects
if(obj.children!=undefined){
obj.children.forEach(function(element){
if(fn(element)){
items.push(element)
}
filter(element,fn,items)
})
}
//Return items
return items
}
Called like:
filter(data.items[0],function(el){
if(el.children != undefined)
return el.children.filter(function(el){
return el.toc_title == "Events"
}).length>0
})
Which works well, but it seems to me that this kind of query would be fairly common... Is there an existing built-in function for doing this job?
Your code seems to work in a correct way, although, you could use a combination between the method map and filter recursively. In this way, you will get a code more efficient.
Here you can find some examples about how to use these functions recursively. An example could be:
let filteredFnc = (jsonObj) => jsonObj.filter(jsonObj => jsonObj.children !== undefined)
let map = (filteredFnc, obj) => !obj.length ? [] : [filteredFnc(obj[0])].concat(map(filtered, obj), obj.slice(1)));

Categories