1

I need to return the value of a specific property of nested objects with ES5 syntax. Every object can have its own structure, so the needed property can be on different levels/places. E.g. -> I have three different objects and the value of property "source" is needed:

  • first_data has that property in list.details.source
  • second_data has that property in list.details.products[0]._new.source
  • third_data does not have this property, therefore it should return false

So how can I return the value of the specific property with consideration, that it can be on any position in object?

var first_data = {
    area: "South",
    code: "S265",
    info: {
        category: "enhanced",
        label: "AB | 27AS53",
        variable: "VR"
    },
    list: {
        area: "Mid",
        details: [
            {
                source: "Spain",
                totals: 12,
                products: [
                    {
                        name: "ABC",
                        brand: "Nobrand",
                        id: "111",
                        category: "Men",
                    }
                ]
            }
        ]
    },
    time: 1654775446138
};

var second_data = {
    area: "South",
    code: "S265",
    info: {
        category: "enhanced",
        label: "AB | 27AS53",
        variable: "VR"
    },
    list: {
        area: "Mid",
        details: [
            {
                products: [
                    {
                        name: "ABC",
                        brand: "Nobrand",
                        id: "111",
                        category: "Men",
                        _new: {
                            source: "Spain",
                            totals: 12
                        }
                    }
                ]
            }
        ]
    },
    time: 1654775446138
};

var third_data = {
    area: "South",
    code: "S265",
    info: {
        category: "enhanced",
        label: "AB | 27AS53",
        variable: "VR"
    },
    list: {
        area: "Mid",
        details: [
            {
                products: [
                    {
                        name: "ABC",
                        brand: "Nobrand",
                        id: "111",
                        category: "Men"
                    }
                ]
            }
        ]
    },
    time: 1654775446138
};

I first tried to solve it with ES6, so that I can rewrite it in a second step into ES5. Here is what I have so far. The first problem is that here I am getting a false, but the property exists.

var propertyExists = function (obj, key) {

  if(obj === null || obj === undefined) {
    return false;
  }
  
  for(const k of Object.keys(obj)) {
    if(k === key) {
      return obj[k]
    }
    else {
      const val = obj[k];
      
       if(typeof val === 'object') {
      
        if(propertyExists(val, key) === true) {
          return true;
        }
      }
    }
  }
  
  return false;
}

propertyExists(first_data, 'source')
rimed
  • 105
  • 7
  • 3
    So what's the question? – Pointy Jun 09 '22 at 14:01
  • 1
    Did you attempt anything? – epascarello Jun 09 '22 at 14:01
  • You might want to look into flattening your JSON first, then iterating through the keys. https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects – Spok Jun 09 '22 at 14:11
  • You can use a recursive algorithm that returns on the first occurrence of the prop – F-nixro Jun 09 '22 at 14:18
  • I updated the questions what I have so far. Ok, so basically I need to stringify the object first and then to return the value? – rimed Jun 09 '22 at 14:24
  • See [this answer](https://stackoverflow.com/a/15643382/218196) – Felix Kling Jun 09 '22 at 14:40
  • 3
    FWIW, I believe your code returns `false` because you return the *value* of the property (`return obj[k]`) but below you are explicitly checking whether the returned value is `true`: `if(propertyExists(val, key) === true) {`. And of course `'Spain' === true` is `false`. – Felix Kling Jun 09 '22 at 14:43

1 Answers1

1

Your propertyExists function didn't work because it returned the value of source but it later checked if the value is equal to true (as described by Felix Kling in a comment above).

Here's my implementation (originally in ES6 but I used a typescript compiler with target set to ES5):

var findProp = function (obj, prop) {
    if (typeof obj != "object") {
        return false;
    }
    if (obj.hasOwnProperty(prop)) {
        return obj[prop];
    }
    for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) {
        var p = _a[_i];
        if (typeof obj[p] === "object") {
            var t = findProp(obj[p], prop);
            if (t) {
                return t;
            }
        }
    }
    return false;
};

Note: It might be faster to detect which object structure it is and retrieve the value because you would then know where it is.

Joachim
  • 71
  • 5