John Glabb
John Glabb

Reputation: 1621

How to find and replace value in JSON?

I have an object like this:

{
  "responses": {
    "firstKey": {
      "items": {
        "name": "test name one"
      }
    },
    "anotherKey": {
      "items": {
        "name": "test name two"
      }
    },
    "oneMoreKey": {
      "items": {
        "name": "John"
      }
    }
  }
}

I need to find all 'name' keys and replace its value only if it starts with 'test name' then return new JSON object:

{
  "responses": {
    "firstKey": {
      "items": {
        "name": "N/A"
      }
    },
    "anotherKey": {
      "items": {
        "name": "N/A"
      }
    },
    "oneMoreKey": {
      "items": {
        "name": "John"
      }
    }
  }
}

The problem is that the keys are not consistent through the objects, i.e. 'firstKey', 'secondKey'... I tried ForEach but it seems to be too cumbersome... So I need either lodash or vanila JavaScript to replace the values.

Upvotes: 1

Views: 42863

Answers (4)

Nicholas Carey
Nicholas Carey

Reputation: 74187

A javascript object is for all intents and purposes a tree — though it can be, and may well be, a directed graph — that quite possibly may be cyclic meaning a node in the graph points back to own of its own parents. Following a cycle can result in never-ending recursion or loop.

You want to use something like traverse to do what you're talking about. It takes care of all the stuff that makes traversing a graph hassle — dealing with cycles in the graph and the like.

const traverse = require('traverse');
. . .
var scrubbed = traverse(obj).map( function(value) {
  const isTestName = this.key === 'name'
    && value
    && /^test name/i.test(value)
    ;

  if (isTestName) {
    this.update('N/A');
  }

});

NOTE: The callback function given to travese can't be an arrow function (() => {...} as that function's this context is the traverse context for the current node being inspected.

That traverse context also gives you access to the entire path from the root down to the current node, along with an upward link to the parent node's traverse context.

Upvotes: 1

Slai
Slai

Reputation: 22866

It can also be done during parsing :

var json = `{
  "responses": {
    "firstKey": {
      "items": {
        "name": "test name one"
      }
    },
    "anotherKey": {
      "items": {
        "name": "test name two"
      }
    },
    "oneMoreKey": {
      "items": {
        "name": "John"
      }
    }
  }
}`

var obj = JSON.parse(json, (k, v) => k == 'name' && /^test name/.test(v) ? 'N/A' : v)

console.log( obj )

Upvotes: 2

Daniel Gale
Daniel Gale

Reputation: 663

The javascript object should be iterated and then each value of name can be checked and replaced. There are checks such as hasOwnProperty() that can be used to make sure you are not iterating objects that are missing "items" or "name" for better error handling.

var data = {
  "responses": {
    "firstKey": {
      "items": {
        "name": "test name one"
      }
    },
    "anotherKey": {
      "items": {
        "name": "test name two"
      }
    },
    "oneMoreKey": {
      "items": {
        "name": "John"
      }
    }
  }
};

Given the JSON above you can use a simple for statement to iterate and then check each name for some value and replace.

for(var key in data.responses){
    if ((data.responses[key].items.name).match(/test name/)){
       data.responses[key].items.name = "N/A";
    } 
}

To check your replacements you can log data to the console.

console.log(JSON.stringify(data));

Upvotes: 2

SteelFeather
SteelFeather

Reputation: 1680

Do something like this. Convert to string replace using regex (add key to regex as well) and then convert back.


var data = {
  "responses": {
    "firstKey": {
      "items": {
        "name": "test name one"
      }
    },
    "anotherKey": {
      "items": {
        "name": "test name two"
      }
    },
    "oneMoreKey": {
      "items": {
        "name": "John"
      }
    }
  }
};

var originalMsg = JSON.stringify(data);
console.log(data)
console.log(originalMsg)
var updatedMsg = originalMsg.replace(/test name [a-z]*/g, "N/A");
console.log(updatedMsg)
var newObj = JSON.parse(updatedMsg); 
console.log(newObj);

Upvotes: 1

Related Questions