1

As the title states, I'm attempting to essentially clean an object to prepare it for POSTing to an API.

The API endpoint does not allow for the empty arrays.

So let's say I have a POST object that looks like this -

{
  "Addresses": [
    {}
  ],
  "Phones": [
    {}
  ],
  "FirstName": "Foo",
  "LastName": "Bar",
  "EmailAddress": "foobar@internet.com",
  "Name": "FooBar"
}

I believe I clean empty objects from the arrays using something like this -

  var addrArr = input.Addresses;
  var phoneArr = input.Phones;
  
    var newAddrArray = addrArr.filter(value => Object.keys(value).length !== 0);
    var newPhoneArray = phoneArr.filter(value => Object.keys(value).length !== 0);

  
  return {
Addresses : newAddrArray,
Phones: newPhoneArray
}

This removes the empty objects from the array. However, this leaves two empty arrays. My thoughts are it would be best to clean the empty objects out, then determine if these arrays are empty, and if they are, (where I need help) remove them from the parent object.

Any help on how to handle this, or, how to do this more efficiently is much appreciated.

Cody Carmichael
  • 177
  • 3
  • 16
  • Might be useful: https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object – Matt Jun 28 '21 at 21:15
  • @trincot they're snippets from two different areas of my workflow.. I've edited to clear up confusion. The input.Addresses is referencing the Addresses array in the post object, likewise, same with Phones. – Cody Carmichael Jun 28 '21 at 21:22

3 Answers3

3

To make it generic (for arbitrary nested data structures), you could use a recursive solution so that there is some cascading effect after you clean out an empty object, making the wrapping object empty, ...etc.

Assuming you also want to remove undefined as values, then return undefined for anything that is not primitive and has no keys, and let the caller remove keys that so receive undefined values.

Code:

function clean(obj) {
    if (Object(obj) !== obj) return obj; // primitives are kept
    obj = Array.isArray(obj)
        ? obj.map(clean).filter(v => v !== undefined)
        : Object.fromEntries(
            Object.entries(obj).map(([k, v]) => [k, clean(v)])
                               .filter(([_, v]) => v !== undefined)
        );
    return Object.keys(obj).length ? obj : undefined;
}

// Demo
let input = {
  "Addresses": [{}],
  "Phones": [{}],
  "FirstName": "Foo",
  "LastName": "Bar",
  "EmailAddress": "foobar@internet.com",
  "Name": "FooBar"
};

console.log(clean(input));
trincot
  • 317,000
  • 35
  • 244
  • 286
0

Is the following what you are asking for?

const addrArr = input.addrArr;
const phoneArr = input.phoneArr;
  
const newAddrArray = addrArr.filter(value => Object.keys(value).length !== 0);
const newPhoneArray = phoneArr.filter(value => Object.keys(value).length !== 0);

const r = {};
if (newAddrArray.length > 0) r.Addresses = newAddrArray;
if (newPhoneArray.length > 0) r.Phones = newPhoneArray;

return r;
SILENT
  • 3,916
  • 3
  • 38
  • 57
  • I like this idea. If I'm not mistaken, this will convert the empty array(s) to an empty object? Then if it's an empty object. I can use something like - if (Object.keys(o[k]).length === 0) { delete o[k]; // The object had no properties, so delete that property } To remove the empty object from the parent POST Object? – Cody Carmichael Jun 28 '21 at 21:26
  • @CodyCarmichael There are multiple ways to do it but my preferred way is not add the prop if its empty in the first place due to javascript's `delete` performance issues. A recursive function can be easily implemented that cleans up the object. – SILENT Jun 28 '21 at 21:38
-1

Seems strange that the API wouldn't support empty arrays. Regardless, this is definitely possible to work around.

const payload = {
  "Addresses": [
    {}
  ],
  "Phones": [
    {}
  ],
  "FirstName": "Foo",
  "LastName": "Bar",
  "EmailAddress": "foobar@internet.com",
  "Name": "FooBar"
};

let cleanedPayload = {
  "FirstName": payload.FirstName,
  "LastName": payload.LastName,
  "EmailAddress": "foobar@internet.com",
  "Name": "FooBar"
};

const isNotEmpty = obj => Object.keys(obj).length !== 0;

const hasPhoneNumbers = payload.Phones.filter(isNotEmpty).length > 0;
const hasAddresses = payload.Addresses.filter(isNotEmpty).length > 0;

if(hasPhoneNumbers) {
  cleanedPayload.Phones = payload.Phones;
}
if(hasAddresses) {
  cleanedPayload.Addresses = payload.Addresses;
}

// pseduo-code
api.post('/my/url', cleanedPayload);

To help clean up this code a bit you can use a library like https://ramdajs.com/ or https://lodash.com/, but definitely not necessary.