Reputation: 397
I want to remove all keys that have values of N/A, - or an empty string. If one of these values appear in the array the I want to remove that single item from the array. So for instance my example output is this:
{"name":{"first":"Daniel","middle":"N/A","last":"Smith"},"age":45}
The output I expect is this
{"name":{"first":"Daniel","last":"Smith"},"age":45}
I have tried this but it does not seem to work:
function recurse(resp) {
let data;
for (var x in resp) {
data = resp[x]
if (data === 'null' || data === null || data === '-' || typeof data === 'undefined' || (data instanceof Object && Object.keys(data).length == 0)) {
delete resp[x];
}
if (data instanceof Object) {
data = recurse(data);
}
}
return resp;
}
Upvotes: 2
Views: 10001
Reputation: 11
You can check out the full solution on github Json Cleaning using C#
static void Main(string[] args)
{
var json = "{\"name\":{\"first\":\"Robert\",\"middle\":\"\",\"last\":\"Smith\"},\"age\":25,\"DOB\":\"-\",\"hobbies\":[\"running\",\"coding\",\"-\"],\"education\":{\"highschool\":\"N\\/A\",\"college\":\"Yale\"}}";
var result = CleanJson(json);
Console.WriteLine(JsonConvert.SerializeObject(result));
}
private static Dictionary<string, dynamic> CleanJson(string json)
{
var data = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(json);
var exclusions = new HashSet<string> { "", "-", "N/A", "n/a" };
Dictionary<string, dynamic> resultDictionary = [];
foreach (var item in data!)
{
var key = item.Key;
var value = item.Value;
switch (value)
{
case long _:
resultDictionary.Add(key, value);
break;
case string str:
if (!exclusions.Contains(str))
resultDictionary.Add(key, str);
break;
case JArray jArray:
var arrResult = new List<string>();
foreach (var itemobj in jArray)
{
var itemStr = itemobj.Value<string>();
if (!exclusions.Contains(itemStr!))
{
arrResult.Add(itemStr!);
}
}
resultDictionary.Add(key, arrResult);
break;
default:
var json2 = JsonConvert.SerializeObject(value);
var result = CleanJson(json2);
resultDictionary.Add(key, result);
break;
}
}
return resultDictionary;
}
Upvotes: 0
Reputation: 1121
Remove all keys that have values of N/A, -, or empty strings. If one of these values appear in an array, remove that single item from the array. For all keys removed, create a key/value pair at the end of the output object with the key items_removed and the value is the count.
Example Input
{"name":{"first":"Daniel","middle":"N/A","last":"Smith"},"age":45}
Example Output
{"name":{"first":"Daniel","last":"Smith"},"age":45, "items_removed": 1}
Solution Node js JSON cleaning
const https = require('https');
let items_removed = 0;
const removedItems = ["N/A", "-", ""];
const cleanObj = obj => {
for(const key in obj) {
if(removedItems.includes(obj[key])) {
delete obj[key];
items_removed++;
} else if(Array.isArray(obj[key])) {
const len = obj[key].length;
let arr = [];
for(let i = 0; i < len; i++) {
let temp = obj[key][i];
if(removedItems.includes(temp)) {
items_removed++;
continue;
}
if(typeof(temp) === 'object') {
temp = cleanObj(temp);
}
arr = arr.concat(temp);
}
obj[key] = arr;
} else if(typeof(obj[key]) === 'object') {
obj[key] = cleanObj(obj[key]);
}
}
return obj;
}
https.get('https://coderbyte.com/api/challenges/json/json-cleaning', (resp) => {
resp.on("data", data => {
const obj = cleanObj(JSON.parse(data.toString()));
console.log(JSON.stringify({...obj, items_removed}));
});
});
Upvotes: 0
Reputation: 31
const obj = {"name":{"first":"Daniel","middle":"N/A","last":"Smith"},"age":50}
const jsonclean = (data) => {
Object.keys(data).map(key => {
if(typeof(data[key]) === 'object'){
jsonclean(data[key]);
} else if(data[key] === 'null' || data[key] == 'N/A' || data[key] === null || data[key] === '-' || typeof data[key] === 'undefined'){
delete data[key];
}
})
return data;
}
const newobj = jsonclean(obj)
console.log(newobj)
Upvotes: 0
Reputation: 4243
you will need to write a recursive function to walk the json tree of nested dictionaries to make it generic. I am demonstrated how to delete an element from an nested dictionary using to keys: the parent key and the child key.
myjson={"name":{"first":"Daniel","middle":"N/A","last":"Smith"},"age":45}
to_delete=[]
for key,item in myjson.items():
if isinstance(item,dict):
for key2,element in item.items():
print(key,key2,element)
if element=='N/A':
to_delete.append({'key':key,'key2':key2})
else:
print(key,item)
print(to_delete)
for item in to_delete:
print(item)
del myjson[item['key']][item['key2']]
print(myjson)
Upvotes: 0
Reputation: 152
I added some additional checks and seem to be working fine for more nested objects.
let obj = {"name":{"first":"Daniel","middle":"N/A","last":"Smith", "innerObject":{"prop1":"random value", "prop2":null, "prop3":"N/A", "prop4":{}}},"age":45};
function recurse(data){
for(let key in data){
if(data[key] instanceof Object){
if(Object.keys(data[key]).length == 0){
delete data[key];
} else {
recurse(data[key]);
}
} else if(data[key] === 'null' || data[key] == 'N/A' || data[key] === null || data[key] === '-' || typeof data[key] === 'undefined' || (data[key] instanceof Object && Object.keys(data[key]).length == 0)){
delete data[key];
}
}
return data;
}
let newobj = recurse(obj)
console.log(newobj)
Please let me know if it works for you! Thanks
Upvotes: 3
Reputation: 745
In order to avoid the max stack size exceeded error, the code will need to be refactored to evaluate the object iteratively. I have adjusted the code to include the suggestion that @Carlos1232 had, and also iterate over the values on the object.
function clean(resp) {
const queue = [resp];
while (queue.length) {
const element = queue.pop();
for (var x in element) {
const data = element[x];
if (data === 'null' || data == 'N/A' || data === null || data === '-' || typeof data === 'undefined' || (data instanceof Object && Object.keys(data).length == 0)) {
delete element[x];
}
if (data instanceof Object) {
queue.push(data);
}
}
}
return resp;
}
Upvotes: 0
Reputation: 815
It is working, just need to add the N/A
validation
let obj = {"name":{"first":"Daniel","middle":"N/A","last":"Smith"},"age":45};
function recurse(resp) {
let data;
for (var x in resp) {
data = resp[x]
if (data === 'null' || data == 'N/A' || data === null || data === '-' || typeof data === 'undefined' || (data instanceof Object && Object.keys(data).length == 0)) {
delete resp[x];
}
if (data instanceof Object) {
data = recurse(data);
}
}
return resp;
}
let newobj = recurse(obj)
console.log(newobj)
Upvotes: 1