2

I am using angular 2 with a datatable to modify a large data set. After the modification I need to save the changes in my database using a spring.

this is the json that I send to the server.

{  
  "id":3,
  "mois":"2017-07-01",
  "status":"Soumise",
  "ligneNoteDeFrais":{  
    "2017-07-10":{  
      "id":1,
      "day":"2017-07-10",
      "fk":{  
        "id":2,
        "description":"frais kilomtrique",
        "nb":5,
        "pu":6,
        "totale":44,
          "typeNoteDeFrais":null
        },
        "preuves":[],
        "detailFrais":{  
          "12":{  
            "id":1,
            "description":"test",
            "nb":5,
            "pu":4,
            "totale":0,
            "typeNoteDeFrais":{  
            "id":12,
            "intitule":"gg",
            "justifiable":true,
            "justificationObligatoire":true,
            "quantifiable":true,
            "new":false
          }
        },
        "14":{ },
        "15":{ },
        "18":{ },
        "19":{ }
      }
    },
    "2017-07-01":{  
      "fk":{ },
      "detailFrais":{  
        "12":{ },
        "14":{ },
        "15":{ },
        "18":{ },
        "19":{ }
      }
    },
    "2017-07-02":{  
      "fk":{ },
      "detailFrais":{  
        "12":{ },
        "14":{ },
        "15":{ },
        "18":{ },
        "19":{ }
      }
    }
  }
}

As you can see there are some empty entrie in this JSON

Is there a solution to delete these entrie before sending them to the server or so that they are not mapped in the object.

0mpurdy
  • 3,198
  • 1
  • 19
  • 28
Mohamed Amine Ouali
  • 575
  • 1
  • 8
  • 23

3 Answers3

3

I adapted this from this stack overflow question's answers but because it's now typescript I think it's sufficiently different.

function removeEmpty(obj) {
  Object.keys(obj).forEach((key) => {
    if (obj[key] && typeof obj[key] === 'object') {
      const childObject = removeEmpty(obj[key]);
      if (childObject === undefined) {
        delete obj[key];
      }
    } else if (obj[key] === '' || obj[key] === null || obj[key] === undefined) {
      delete obj[key];
    }
  });
  return Object.keys(obj).length > 0 || obj instanceof Array ? obj : undefined;
};

let json = {
  "id": 3,
  "mois": "2017-07-01",
  "status": "Soumise",
  "ligneNoteDeFrais": {
    "2017-07-10": {
      "id": 1,
      "day": "2017-07-10",
      "fk": {
        "id": 2,
        "description": "frais kilomtrique",
        "nb": 5,
        "pu": 6,
        "totale": 44,
        "typeNoteDeFrais": null
      },
      "preuves": [],
      "detailFrais": {
        "12": {
          "id": 1,
          "description": "test",
          "nb": 5,
          "pu": 4,
          "totale": 0,
          "typeNoteDeFrais": {
            "id": 12,
            "intitule": "gg",
            "justifiable": true,
            "justificationObligatoire": true,
            "quantifiable": true,
            "new": false
          }
        },
        "14": {},
        "15": {},
        "18": {},
        "19": {}
      }
    },
    "2017-07-01": {
      "fk": {},
      "detailFrais": {
        "12": {},
        "14": {},
        "15": {},
        "18": {},
        "19": {}
      }
    },
    "2017-07-02": {
      "fk": {},
      "detailFrais": {
        "12": {},
        "14": {},
        "15": {},
        "18": {},
        "19": {}
      }
    }
  }
}

console.log(removeEmpty(json));

I have this inside a service which I inject wherever I need this functionality.

Note that this will delete any key that is:

  • undefined
  • null
  • empty string ''
  • empty object {}

but not empty array: []

so

{ field: 'data', field2: {}, field3: undefined, field4: null, field5: '', field6: 6, field7: [] }

will become

{ field: 'data', field6: 6, field7: [] }
0mpurdy
  • 3,198
  • 1
  • 19
  • 28
  • Thank you, but it didn't work I think that because there are actually an object that does't have any attribute. so when I stringify this object I only get empty braces. When I debug with my browser it say that there are an object but it does not have any attribute. – Mohamed Amine Ouali Jul 25 '17 at 18:04
  • should I use this function on the object or on the json – Mohamed Amine Ouali Jul 25 '17 at 18:06
  • I have updated the answer - did you get my most recent edit? unfortunately the original didn't include removing empty objects sorry! Use it on the object before stringifying it – 0mpurdy Jul 25 '17 at 18:06
  • I have tried the recent one, now it removed the "ligneNoteDeFrais" object even if it is not empty. I have try it on the exemple above and it have deleted the hole object. now I get only "id":3, "mois":"2017-07-01", "status":"Soumise", – Mohamed Amine Ouali Jul 25 '17 at 18:15
  • 1
    That function takes way too much effort to read; you should split up that condition instead of abusing `&&` and `||` to short-circuit. – royhowie Jul 25 '17 at 18:25
  • @royhowie you are right of course, I knew I had this working in my own personal project, now I'm regretting posting as is because I can't adapt it to the question as quickly as I would like! – 0mpurdy Jul 25 '17 at 18:27
  • @MohamedAmineOuali I followed merzelin's example and now you can see the code working on your data for yourself – 0mpurdy Jul 25 '17 at 18:40
  • @0mpurdy I think that I will stick to the original solution :) thanks. I really like the logic operators. :p – Mohamed Amine Ouali Jul 25 '17 at 18:48
2

This solution is crafted specifically to object structure provided in the question

function isEmptyObject(obj) {
  return !Boolean(Object.keys(obj).length)
}

function removeEmpty(data) {
  for (let noteKey in data.ligneNoteDeFrais) {
    const note = data.ligneNoteDeFrais[noteKey]
    if (isEmptyObject(note.fk)) {
      delete note.fk
    }
    for (let detail in note.detailFrais) {
      if (isEmptyObject(note.detailFrais[detail])) {
        delete note.detailFrais[detail]
      }
    }
    if (isEmptyObject(note.detailFrais)) {
      delete note.detailFrais
    }
    if (isEmptyObject(note)) {
      delete data.ligneNoteDeFrais[noteKey]
    }
  }
}

const data = {
  "id": 3,
  "mois": "2017-07-01",
  "status": "Soumise",
  "ligneNoteDeFrais": {
    "2017-07-10": {
      "id": 1,
      "day": "2017-07-10",
      "fk": {
        "id": 2,
        "description": "frais kilomtrique",
        "nb": 5,
        "pu": 6,
        "totale": 44,
        "typeNoteDeFrais": null
      },
      "preuves": [

      ],
      "detailFrais": {
        "12": {
          "id": 1,
          "description": "test",
          "nb": 5,
          "pu": 4,
          "totale": 0,
          "typeNoteDeFrais": {
            "id": 12,
            "intitule": "gg",
            "justifiable": true,
            "justificationObligatoire": true,
            "quantifiable": true,
            "new": false
          }
        },
        "14": {

        },
        "15": {

        },
        "18": {

        },
        "19": {

        }
      }
    },
    "2017-07-01": {
      "fk": {

      },
      "detailFrais": {
        "12": {

        },
        "14": {

        },
        "15": {

        },
        "18": {

        },
        "19": {

        }
      }
    },
    "2017-07-02": {
      "fk": {

      },
      "detailFrais": {
        "12": {

        },
        "14": {

        },
        "15": {

        },
        "18": {

        },
        "19": {

        }
      }
    }

  }
}


removeEmpty(data)
console.log(data)
marzelin
  • 10,790
  • 2
  • 30
  • 49
  • This is an excellent answer to the specific question +1, however I'm going to leave mine as it should solve the problem for anyone else with a similar problem. – 0mpurdy Jul 25 '17 at 18:39
2

Thank you guys I manage to correct the solution proposed by 0mpurdy.

removeEmpty(obj) {
        Object.keys(obj).forEach((key) => {
            (obj[key] && typeof obj[key] === 'object') && (obj[key]=this.removeEmpty(obj[key]));
            (obj[key] === '' || obj[key] === null || obj[key] === undefined) && delete obj[key];
        });
        return Object.keys(obj).length > 0 ? obj : undefined;
    };

Thanks you too marzelin.

Mohamed Amine Ouali
  • 575
  • 1
  • 8
  • 23