skip to Main Content

I have a JS object like this:

{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":""}]"}

I would like to create a function which returns such object without field which is string-array "settings":"[{"ip":""}]" and if this array contains only one element and if this object contains only one key-value pair with value of empty string.

Desired result is:

{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26"}

Arrays not to be filtered:

{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"33333not empty"}]"}

or:

{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"345", "dns": "address"}]"}

I wrote the following function:

    function filterArrayFields(values) {
  const result = {};

  const fieldNames = Object.keys(values);

  fieldNames.forEach((fieldName) => {
    if (typeof values[fieldName] !== 'string') {
      result[fieldName] = values[fieldName];
      return;
    }

    try {
      const parsedValue = JSON.parse(values[fieldName]);

      if (!Array.isArray(parsedValue)) {
        result[fieldName] = values[fieldName];
        return;
      }

      if (Array.isArray(parsedValue) && parsedValue.length > 1) {
        result[fieldName] = values[fieldName];
        return;
      }

      if (Array.isArray(parsedValue) && parsedValue.length === 1) {
        const arrayTypeFieldValue = parsedValue[0];

        const [arrayTypeFieldValueName] = Object.keys(arrayTypeFieldValue);

        if (arrayTypeFieldValue[arrayTypeFieldValueName] !== '') {
          result[fieldName] = values[fieldName];
          return;
        }
      }
    } catch (error) {
      result[fieldName] = values[fieldName];
    }
  });

  return result;
}

This method is working correctly but it looks like that it is overloaded buy if-s or extra conditions. Is it possible to optimize this function anyhow?

Edit: our target field can have any name, not only ‘settings’ – ‘settings’ here is just an example

2

Answers


  1. I think you could tighten this up significantly by shallow-cloning the input object via the spread operator and conditionally merging the settings back in only if it meets your criteria.

    The criteria testing could be handled by a separate dedicated function. Something like this:

    function stripEmptySettings (obj) {
      const { settings, ...rest } = obj;
      return {
        ...rest,
        ...stripSettings(JSON.parse(settings)),
      }
    }
    
    function stripSettings (settings) {
      if (
        settings?.length === 1
        && Object.keys(settings[0]).length === 1
        && Object.values(settings[0]).every(v => v === '')
      ) {
        return;
      }
      return {settings};
    }
    
    const inputs = [
      {"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":""}]"},
      {"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"33333not empty"}]"},
      {"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"345", "dns": "address"}]"}
    ]
    
    const results = inputs.map(stripEmptySettings);
    
    console.log(JSON.stringify(results, null, 3));
    Login or Signup to reply.
  2. JS has a builtin filter function. For the settings value using JSON.stringify() and JSON.parse() will be the easiest way to serialize the array

    const filteredList = fieldNames.filter(field => {
      if("settings" in field){
        let settings = JSON.parse(field.settings)
        if(
          settings.length > 0 &&
          settings[0]
          ){
            let nonEmpty = false
            const keys = Object.keys(settings[0])
            for(let i =0; i < keys.length; i ++){
              if(settings[0][keys[i]]){
                nonEmpty = true
                break
              }
            }
            return nonEmpty
        }
        return false
      }
      return true
    })
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search