Saad
Saad

Reputation: 397

Node js JSON cleaning

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

Answers (7)

Chidi Jude
Chidi Jude

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

Md. Jahid Hossain
Md. Jahid Hossain

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

Dhruvin Modi
Dhruvin Modi

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

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

rudy0807
rudy0807

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

joncloud
joncloud

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

Carlos1232
Carlos1232

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

Related Questions