rockZ
rockZ

Reputation: 875

Update JSON on specific key at unknown position

Lets assume I have the following JSON string

var storage =   {
        "gear": {
            "gear-type-small": {
                "type": "gear",
                "visible": false,
                "gear-type-small-1": {
                    "type": "armor",
                    "price": 50,
                    "unlocked": true,
                    "bought": false
                },
                "gear-type-small-2": {
                    "type": "weapon",
                    "price": 100,
                    "unlocked": true,
                    "bought": false
                }
            }
        }
    }

And I wanna read and also write data to it. To do that I need to know the location of each node. For example.

storage['gear']['gear-type-small']['visible'] = true;

But select the right node like this seems a little odd to me. If I knew that a node is unique like gear-type-small-2 in gear-type-small is it somehow possible to manipulate this node directly whitout knowing the full path to it?

In this example 'find unlocked in gear-type-small-2 and set it to true' But whitout knowing where gear-type-small-2 exactly is.

Upvotes: 0

Views: 98

Answers (3)

antonku
antonku

Reputation: 7675

You can leverage replacer function of JSON.stringify to update the value and then parse the JSON string back to an object.

var storage =   {
  "gear": {
    "gear-type-small": {
      "type": "gear",
      "visible": false,
      "gear-type-small-1": {
        "type": "armor",
        "price": 50,
        "unlocked": false,
        "bought": false
      },
      "gear-type-small-2": {
        "type": "weapon",
        "price": 100,
        "unlocked": false,
        "bought": false
      }
    }
  }
}

var result = JSON.parse(JSON.stringify(storage, function (key, value) {
  if (key === 'gear-type-small-2') {
    value.unlocked = true
  }
  return value
}));

console.log(result)

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386746

You could specify part properties and update the last given property.

function fuzzyUpdate(object, path, value) {
    if (!object || typeof object !== 'object') return;
    Object.keys(object).forEach(k => {
        if (k === path[0]) {
            if (path.length === 1) {
                object[k] = value;
            } else {
                fuzzyUpdate(object[k], path.slice(1), value);
            }
            return;
        }
        fuzzyUpdate(object[k], path, value);
    });
}

var storage = { gear: { "gear-type-small": { type: "gear", visible: false, "gear-type-small-1": { type: "armor", price: 50, unlocked: true, bought: false }, "gear-type-small-2": { type: "weapon", price: 100, unlocked: true, bought: false } } } };

fuzzyUpdate(storage, ['gear-type-small-2', 'unlocked'], 42);

console.log(storage);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

charlietfl
charlietfl

Reputation: 171690

You can use Object.entries() and Object.values() to iterate objects and look for what you want.

Something like:

var storage = {
  "gear": {
    "gear-type-small": {
      "type": "gear",
      "visible": false,
      "gear-type-small-1": {
        "type": "armor",
        "price": 50,
        "unlocked": true,
        "bought": false
      },
      "gear-type-small-2": {
        "type": "weapon",
        "price": 100,
        "unlocked": true,
        "bought": false
      }
    }
  }
}

Object.entries(storage.gear).forEach(([k, obj]) => {
  Object.values(obj).forEach(v => {
    if (typeof v === 'object' && v.hasOwnProperty('unlocked')) {
      v.visible = v.unlocked;
    }
  });
});

console.log(storage)
.as-console-wrapper {	max-height: 100%!important;}

Upvotes: 0

Related Questions