1

I have a complex JSON like this:

{
  "a": {
    "b": {
      "c": {
        "price": {
          "type": "coin",
          "value": "currency"
        }
      }
    }
  },
  "e": {
    "f": {
      "price": {
        "type": "note",
        "value": "currency"
      }
    }
  },
  "price": {
    "type": "cents",
    "value": "dollars"
  }
}

I am trying to write a JavaScript function that will find "price" at any location and pull out the "type" and "value" for it. So my output should be:

"coin" : "currency"
"note" : "currency"
"cents" : "dollars"
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
user3920295
  • 889
  • 2
  • 13
  • 31
  • You could use recursion. Let me try to add an example – Luis felipe De jesus Munoz Jun 13 '18 at 14:43
  • well figure out how to loop recursively – epascarello Jun 13 '18 at 14:44
  • By the time you're trying to do this, you're not dealing with JSON (anymore, or at all, it depends on how you got the data in the first place -- i.e., you may never have been dealing with JSON). You're just dealing with objects. JSON is a *textual notation* for data exchange. [(More here.)](http://stackoverflow.com/a/2904181/157247) If you're dealing with JavaScript source code, and not dealing with a *string*, you're not dealing with JSON. – T.J. Crowder Jun 13 '18 at 14:44

4 Answers4

3

You can create recursive function with for...in loop to return object as a result.

const data = {"a":{"b":{"c":{"price":{"type":"coin","value":"currency"}}}},"e":{"f":{"price":{"type":"note","value":"currency"}}},"price":{"type":"cents","value":"dollars"}}

function getPrice(data) {
  const result = {}
  for (let i in data) {
    if (typeof data[i] == 'object') Object.assign(result, getPrice(data[i]))
    if (i == "price") Object.assign(result, {
      [data[i].type]: data[i].value
    })
  }
  return result;
}

const result = getPrice(data);
console.log(result)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
3

You could check the wanted key price and take type and value for a new object, or look deeper.

function flat(object) {
    return Object.entries(object).reduce(
        (r, [k, v]) => Object.assign(r, k === 'price' ? { [v.type]: v.value } : flat(v)),
        {}
    );
}

var object = { a: { b: { c: { price: { type: "coin", value: "currency" } } } }, e: { f: { price: { type: "note", value: "currency" } } }, price: { type: "cents", value: "dollars" } };

console.log(flat(object));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You need to recursively (or not) iterate on the properties of your object. Here is some old-school javascript:

const testObj =  {
    "a":{
        "b" : {
            "c" :{
                "price" : {
                    "type" : "coin",
                    "value" : "currency"
                }
            }
        }
    },
    "e" : {
        "f" : {
            "price" : {
                "type" : "note",
                "value": "currency"
            }
        }
    },
    "price": {
        "type": "cents",
        "value": "dollars"
    }
};

function findOccurences(accum, obj, prop) {
  if(obj.hasOwnProperty(prop)) {
     accum.push(obj[prop]);
  }
  for(var p in obj) {
    if(obj.hasOwnProperty(p) && p !== prop)
      findOccurences(accum, obj[p], prop);
  }
}
var accum = [];
findOccurences(accum, testObj, "price");
console.log(accum);
Regis Portalez
  • 4,675
  • 1
  • 29
  • 41
1

While the other answers are good, they don't allow different values for the same key. For example, if you have an additional price like this:

"g": {
  "price": {
    "type": "coin",
    "value": "dollars"
  }
}

It will overwrite the first value of coin with the other answers and you will end up with:

{
  "coin": "dollars",
  "note": "currency",
  "cents": "dollars"
}

If you have that scenario and want to get the two different values of coin, you'll need to use a separate object for each key/value instead of making them properties of a single object:

var json = {
  "a": {
    "b": {
      "c": {
        "price": {
          "type": "coin",
          "value": "currency"
        }
      }
    }
  },
  "e": {
    "f": {
      "price": {
        "type": "note",
        "value": "currency"
      }
    }
  },
  "price": {
    "type": "cents",
    "value": "dollars"
  },
  "g": {
    "price": {
      "type": "coin",
      "value": "dollars"
    }
  }
};

function getPrice(data) {
  var result = [];
  for (let i in data) {
    if (i == "price")
      result.push({
        [data[i].type]: data[i].value
      });
    else if (typeof data[i] == "object")
      result.push(getPrice(data[i])[0]);
  }
  return result;
}

var price = getPrice(json);
console.log(price)
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55