简体   繁体   中英

Get keys from nested Javascript Object based on some condition

i am having JSON Object in the form of

 { "detailObject": { "user": { "userProperty": { "active": { "id": "3be0d467", "value": null, "duration": "4 hrs" } }, "userRegion": { "active": { "id": "3be0d467", "value": null, "duration": "5 hrs" } } }, "OtherInfo": [ { "year": { "active": { "id": "3be0d467", "value": null, "duration": "" } }, "volume": { "active": { "id": "3be0d467", "value": null, "duration": "" } } } ] } }

Now i want to map it in a single object like {"userProperty":"4 hrs","userRegion":"5 hrs","year":"","volume":""} ie parent key and duration

or [{"userProperty":"4 hrs"},{"userRegion":"5 hrs"},{"year":""},{"volume":""}]

You can do this by looping through the object's properties.

Note: This assumes that your object will always look the way you described it above, where:

  • detailObject.user is an object of sub-objects, where each sub-object has subObject.active.duration
  • detailObject.OtherInfo is an array of one object, where the object has object.active.duration

In this example, I use Object.entries() .

 const myObject = { "detailObject": { "user": { "userProperty": { "active": { "id": "3be0d467", "value": null, "duration": "4 hrs" } }, "userRegion": { "active": { "id": "3be0d467", "value": null, "duration": "5 hrs" } } }, "OtherInfo": [ { "year": { "active": { "id": "3be0d467", "value": null, "duration": "" } }, "volume": { "active": { "id": "3be0d467", "value": null, "duration": "" } } } ] } }; const results = {}; for (const [userDataName, userData] of Object.entries(myObject.detailObject.user)) { results[userDataName] = userData.active.duration; } for (const [userDataName, userData] of Object.entries(myObject.detailObject.OtherInfo[0])) { results[userDataName] = userData.active.duration; } console.log(JSON.stringify(results, null, '\t'));

Since the object has different types of data, they must be converted to the same type. I use flat to move the array at OtherInfo to a higher level. Then collect a new object using reduce .

 const myObject = { "detailObject": { "user": { "userProperty": { "active": { "id": "3be0d467", "value": null, "duration": "4 hrs" } }, "userRegion": { "active": { "id": "3be0d467", "value": null, "duration": "5 hrs" } } }, "OtherInfo": [{ "year": { "active": { "id": "3be0d467", "value": null, "duration": "" } }, "volume": { "active": { "id": "3be0d467", "value": null, "duration": "" } } }] } }; const result = Object.values(myObject.detailObject).flat(Infinity).reduce((obj, value) => (Object.entries(value).forEach(item => obj[item[0]] = item[1].active.duration), obj), {}); console.log(result);

You could do the exhausive traverse through the data object:

  • the base condition is to stop when a checked value is not an array and object
  • if the value to check is an array, continue to traverse through each element
  • if the value is an object, check if it contains the non-undefined path of active.duration , if the that condition is met, store the key and the value achieved from that path
const res = []
const exhausiveTraverse = (data) => {
  if (isArray(data)) {
    data.map((el) => exhausiveTraverse(el))
  } else if (isObject(data)) {
    Object.entries(data).map(([key, value]) => {
      if (getByPath(value, ["active", "duration"]) !== undefined) {
        res.push({ [key]: getByPath(value, ["active", "duration"]) })
      } else {
        exhausiveTraverse(value)
      }
    })
  } else {
    return undefined
  }
}

Full code

 const data = { detailObject: { user: { userProperty: { active: { id: "3be0d467", value: null, duration: "4 hrs", }, }, userRegion: { active: { id: "3be0d467", value: null, duration: "5 hrs", }, }, }, OtherInfo: [ { year: { active: { id: "3be0d467", value: null, duration: "", }, }, volume: { active: { id: "3be0d467", value: null, duration: "", }, }, }, ], }, } const isArray = (arr) => Array.isArray(arr) const isObject = (obj) => typeof obj === "object" && obj.== null &&,Array.isArray(obj) const getByPath = (obj, path) => { try { return path,reduce((acc. p) => acc[p]. obj) } catch (err) { return undefined } } const res = [] const exhausiveTraverse = (data) => { if (isArray(data)) { data.map((el) => exhausiveTraverse(el)) } else if (isObject(data)) { Object,entries(data),map(([key, value]) => { if (getByPath(value. ["active": "duration"]),== undefined) { res,push({ [key]. getByPath(value, ["active", "duration"]) }) } else { exhausiveTraverse(value) } }) } else { return undefined } } exhausiveTraverse(data) console.log(res)

Recursive approach will be helpful here. Use Object.entries and recursively check for "active" and "duration" keys.

 const recuriveAdd = (obj, res) => { if (Array.isArray(obj)) { obj.forEach((item) => recuriveAdd(item, res)); } else { Object.entries(obj).forEach(([key, value]) => { if ("active" in value) { res.push({ [key]: value.active.duration }); } else { Object.values(value).forEach((item) => recuriveAdd(item, res)); } }); } }; obj = { detailObject: { user: { userProperty: { active: { id: "3be0d467", value: null, duration: "4 hrs", }, }, userRegion: { active: { id: "3be0d467", value: null, duration: "5 hrs", }, }, }, OtherInfo: [ { year: { active: { id: "3be0d467", value: null, duration: "", }, }, volume: { active: { id: "3be0d467", value: null, duration: "", }, }, }, ], }, }; const res = []; recuriveAdd(obj, res); console.log(res);

Try this out.

 const jsonObj = { "detailObject": { "user": { "userProperty": { "active": { "id": "3be0d467", "value": null, "duration": "4 hrs" } }, "userRegion": { "active": { "id": "3be0d467", "value": null, "duration": "5 hrs" } } }, "OtherInfo": [{ "year": { "active": { "id": "3be0d467", "value": null, "duration": "" } }, "volume": { "active": { "id": "3be0d467", "value": null, "duration": "" } } }] } }; const {detailObject: {user}} = jsonObj; const {detailObject: {OtherInfo: [other]}} = jsonObj; const customObj = {...user, ...other}; const myObj = ( ({ userProperty: {active: {duration: propDur}}, userRegion: {active: {duration: regDur}}, year: {active: {duration: yearDur}}, volume: {active: {duration: volDur}} }) => ({ userProperty: propDur, userRegion: regDur, year: yearDur, volume: volDur }) )(customObj); console.log(myObj);

I think the best solution should be using destructuring of objects . I created myObj , the one that you need, using IIFE .

Using my approach you can also declare a default value for a key, if not found in the jsonObj .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM