web-dev-qa-db-fra.com

Est-il possible de renommer les clés d’objet js à l’aide de underscore.js

J'ai besoin de convertir un objet js en un autre objet pour le transmettre à un serveur où les noms des clés diffèrent, par exemple

var a = {
    name : "Foo",
    amount: 55,
    reported : false,
    ...
    <snip/>
    ...
    date : "10/01/2001"
    } 

doit se transformer en 

a = {
  id : "Foo",
  total : 55,
  updated: false,
  ...
  <snip/>
  ... 
  issued : "10/01/2001"
  }

où j'ai obj lookup disponible pour mapper toutes les clés

var serverKeyMap = {
    name : "id",
    amount : "total",
    reported : "updated",
     ...
    date : "issue"
    }

Existe-t-il une fonction disponible dans underscore.js ou jQuery que je peux utiliser pour effectuer cette fonctionnalité? 

merci

56
claya

Autant que je sache, aucune fonction n'est intégrée à l'une ou l'autre de ces bibliothèques. Vous pouvez faire votre propre assez facilement, cependant: http://jsfiddle.net/T9Lnr/1/ .

var b = {};

_.each(a, function(value, key) {
    key = map[key] || key;
    b[key] = value;
});
30
pimvdb

Je sais que vous n'avez pas mentionné lodash et que les réponses permettent déjà de résoudre le problème, mais quelqu'un d'autre pourrait tirer parti d'une alternative.

Comme @CookieMonster mentionné dans les commentaires, vous pouvez le faire avec _.mapKeys :

_.mapKeys(a, function(value, key) {
    return serverKeyMap[key];
});

Et le violon: http://jsfiddle.net/cwkwtgr3/

57
Samir Aguiar

Semblable à @pimvdb, vous pouvez aussi le faire avec un _.reduce:

_.reduce(a, function(result, value, key) {
    key = map[key] || key;
    result[key] = value;
    return result;
}, {});

Fiddle: http://jsfiddle.net/T9Lnr/39/

39
dule

Vous pouvez copier les valeurs dans les nouvelles propriétés avec JavaScript standard et supprimer les propriétés d'origine avec omit , comme suit:

a.id = a.name;
a.total = a.amount;
a.updated = a.reported;
a = _.omit(a, 'name', 'amount', 'reported');
10
user2387823

C'est résolu ici https://stackoverflow.com/a/30940370/1360897

var keyMapping = {'PropertyA': 'propertyA', ..., 'PropertyF': 'propertyNEW'}

et aussi une cartographie des valeurs anciennes et nouvelles, comme celle-ci

var valueMapping = {'Y': true, 'F': false}

Et ensuite, en utilisant _.map et _.transform, vous pouvez transformer l'objet, comme ceci

var result = _.map(allItems, function(currentObject) {
    return _.transform(currentObject, function(result, value, key) {
        if (key === 'PropertyF' || key === 'PropertyG') {
            value = valueMapping(value);
        }
        result[keyMapping[key]] = value;
    });
});
2
aemonge

J'ai un opérateur de transformation et je voudrais juste l'appliquer à toutes les clés. J'ai fourré le violon de pimvdb pour produire un exemple simple. Dans ce cas, il capitalise la clé. Et cela construit dynamiquement le clavier, ce dont j'avais besoin pour que tout fonctionne bien (merci JSFiddle).

Voici le code modifié:

var keymap = {};
_.each(a, function(value, key) {
    var oldkey = key;
    key = capitalize(key);
    keymap[oldkey] = key;
});
_.each(a, function(value, key) {
    key = keymap[key] || key;
    b[key] = value;
});

Fiddle: http://jsfiddle.net/mr23/VdNjf/

1
mr23

Non, aucune des bibliothèques ne renomme explicitement les clés. Votre méthode est également la plus rapide (voir jsperf tests .) Votre meilleur choix est, si possible, de refactoriser le code côté client ou côté serveur afin que les objets soient identiques.

1
JaredMcAteer
// key_map: {old_name1: new_name1, ... }
function rename_keys(object, key_map, is_picked=false){
  keys = _.keys(key_map);
  new_keys = _.values(key_map);
  picked = _.pick(object, keys);
  renamed = _.object(new_keys, _.values(picked));
  if(is_picked) return renamed;

  return _.chain(object).omit(keys).extend(renamed).value();
}

Cela peut être plus lent que les réponses ci-dessus.

1
Zin Kanzaki

Pourquoi n'utilisez-vous pas ce script Java simple? La valeur d'une paire clé: valeur doit être chaîne/nombre/booléen.

<script type="text/javascript">    
    var serverKeyMap = {
        name : "id",
        amount : "total",
        reported : "updated"
    };

    var a = {
        name : "Foo",
        amount: 55,
        reported : false
    };

    var b={}; // b is object where you will get your output

    for(i in serverKeyMap) b[serverKeyMap[i]]=a[i];

    console.log(b); // It gives what you need.

</script>
1
Umesh Patil

Comme user2387823 disait ci-dessus ???? utiliser omit est une excellente option. Par exemple, vous pourriez écrire quelque chose comme ceci

function updateObjKey(obj, currentKey, newKey) {
    var keyValue = obj[currentKey];
    obj = _.omit(obj, [currentKey]);
    obj[newKey] = keyValue;
    return obj;
  }
0
Brandon Howard

cette version ES2015/2017 ????

function objectMap(source,keyMap) {
    return Object.entries(keyMap).reduce((o,[key , newKey]) => {
            o[newKey]=source[key]
            return o;},{})
}

const obj = {
    name : "Foo",
    amount: 55,
    reported : false,
    date : "10/01/2001"
    }
    
const  serverKeyMap = {
    name : "id",
    amount : "total",
    reported : "updated",
    date : "issue"
    }
    
const result = objectMap(obj,serverKeyMap);

console.log('???? =>' , result);

[Object.entries][1] est es2017 feture retournera la clé d'objet et la valeur sous forme de tableau

[["name", "id"],["amount", "total"],...]
0
malbarmawi