15

I am checking the attributes in a JavaScript object, replacing some of the keys by deleting the prefix "element" and saving the new values in another object.

var keys = Object.keys(json);
for (var j=0; j < keys.length; j++) {
   key = keys[j].replace("element_", "");
   switch(key) {
   default :
      tmp[key] = json[key];
      break;
   }
}

The matter is that when I do that, I can log all the keys, they have the correct names, but when I try to set the values associated to these keys, they are undefined (json[key]).

Is that due to the fact that I converted the keys (Objects) to Strings (with the replace method)?

1
  • What is the purpose of the switch statement? Commented Sep 8, 2015 at 8:08

5 Answers 5

34

We'll write a little function to fix the key the way you want.

function fix_key(key) { return key.replace(/^element_/, ''); }

Underscore

_.object(
  _.map(_.keys(json), fix_key),
  _.values(json)
)

ES5/loop

var keys = Object.keys(json);
var result = {};

for (i = 0; i < keys.length; i++) {
  var key = keys[i];
  result[fix_key(key)] = json[key];
}

return result;

ES5/reduce

Object.keys(json) . reduce(function(result, key) {
  result[fix_key(key)] = json[key];
  return result;
}, {});

ES6

Object.assign(
  {},
  ...Object.keys(json) .
    map(key => ({[fix_key(key)]: json[key]}))
)

This makes an array of little objects each with one key-value pair, using the ES6 "computed property name" feature, then passes them to Object.assign using the ES6 "spread" operator, which merges them together.

Sign up to request clarification or add additional context in comments.

5 Comments

Why do we need to add the most outer parentheses here: ({[fix_key(key)]: json[key]}) ? thanks
Because otherwise the curly bracket would be taken as the beginning of a JS code block, instead of the beginning of an object literal.
I see. How does it work then, is it just applying the parentheses priority in code execution?
The parentheses have no effect on semantics, just as 2 is identical to (2). In this case, they merely enclose an object literal. The effect is the same as writing ({a: 1}) anywhere.
Fantastic. The ES6 solution is super elegant. Much appreciated.
4

The problem is that you are looking for the property in the original object using the new key. Use keys[j] instead of key:

var keys = Object.keys(json);
for (var j=0; j < keys.length; j++) {
   var key = keys[j].replace(/^element_/, "");
   tmp[key] = json[keys[j]];
}

I uses a regular expression in the replace so that ^ can match the beginning of the string. That way it only replaces the string when it is a prefix, and doesn't turn for example noexample_data into no_data.

Note: What you have is not "a json", it's a JavaScript object. JSON is a text format for representing data.

Is that due to the fact that I converted the keys (Objects) to Strings (with the replace method)?

No. The keys are strings, not objects.


You could also change the properties in the original object by deleting the old ones and adding new:

var keys = Object.keys(json);
for (var j=0; j < keys.length; j++) {
   if (keys[j].indexOf("element_") == 0) {
     json[keys[j].substr(8)] = json[keys[j]];
     delete json[keys[j]];
   }
}

Comments

3

Try this:

var keys = Object.keys(json);
for (var j=0; j < keys.length; j++) {
   var key = keys[j]; // key
   var value = json[key]; // data
   delete json[key]; // deleting data with old key
   key = key.replace("element_", ""); // renaming key
   json[key] = value; // setting data with new key
}

or extend prototype of Object

Object.prototype.renameKey = function (oldName, newName) {
    if (!newName) return this;
    if (oldName === newName) return this;

    if (this.hasOwnProperty(oldName)) {
        this[newName] = this[oldName];
        delete this[oldName];
    }
    return this;
};

var keys = Object.keys(json);
keys.forEach(function(key) { json.renameKey(key, key.replace('element_', ''); });

Comments

3

ES2019

Object.fromEntries(
  Object.entries(json).map(([k,v]) => [k.replace('element_', ''), v])
);

Comments

2

key is not original json because you have remove element_ prefix

var keys = Object.keys(json);
for (var j=0; j < keys.length; j++) {
   key = keys[j].replace("element_", "");
   var _key = keys[j];
   switch(key) {
   default :
      tmp[key] = json[_key];
      break;
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.