Comment résoudre TypeError: impossible de convertir undefined ou null en objet

90

J'ai écrit quelques fonctions qui répliquent efficacement JSON.stringify (), convertissant une plage de valeurs en versions stringifiées. Lorsque je porte mon code sur JSBin et que je l'exécute sur des exemples de valeurs, cela fonctionne très bien. Mais j'obtiens cette erreur dans un coureur de spécifications conçu pour tester cela.

Mon code:

  // five lines of comments
  var stringify = function(obj) {
  if (typeof obj === 'function') { return undefined;}  // return undefined for function
  if (typeof obj === 'undefined') { return undefined;} // return undefined for undefined
  if (typeof obj === 'number') { return obj;} // number unchanged
  if (obj === 'null') { return null;} // null unchanged
  if (typeof obj === 'boolean') { return obj;} // boolean unchanged
  if (typeof obj === 'string') { return '\"' + obj + '\"';} // string gets escaped end-quotes
  if (Array.isArray(obj)) { 
    return obj.map(function (e) {  // uses map() to create new array with stringified elements
        return stringify(e);
    });
  } else {
    var keys = Object.keys(obj);   // convert object's keys into an array
    var container = keys.map(function (k) {  // uses map() to create an array of key:(stringified)value pairs
        return k + ': ' + stringify(obj[k]);
    });
    return '{' + container.join(', ') + '}'; // returns assembled object with curly brackets
  }
};

var stringifyJSON = function(obj) {
    if (typeof stringify(obj) != 'undefined') {
        return "" + stringify(obj) + "";
    }
};

Le message d'erreur que je reçois du testeur est:

TypeError: Cannot convert undefined or null to object
    at Function.keys (native)
    at stringify (stringifyJSON.js:18:22)
    at stringifyJSON (stringifyJSON.js:27:13)
    at stringifyJSONSpec.js:7:20
    at Array.forEach (native)
    at Context.<anonymous> (stringifyJSONSpec.js:5:26)
    at Test.Runnable.run (mocha.js:4039:32)
    at Runner.runTest (mocha.js:4404:10)
    at mocha.js:4450:12
    at next (mocha.js:4330:14)

Cela semble échouer avec: stringifyJSON (null) par exemple

zahabba
la source
1
veuillez fournir l'entrée pour laquelle vous obtenez une erreur, car cela fonctionne pour stringifyJSON ({a: 'b', c: 'd'})
vinayakj
1
Mis à part l'erreur, les stringifyJSON([1,2,3])retours 1,2,3et les stringifyJSON({foo: 'bar'})retours {foo: "bar"}, qui ne sont pas tous deux JSON valides.
Felix Kling
4
Ma conjecture serait cette ligne if (obj === 'null') { return null;} // null unchanged, - qui ne passera pas une fois donnée null, seulement si la chaîne est donnée "null". Donc, si vous passez la nullvaleur réelle à votre script, elle sera analysée dans la partie Objet du code. Et Object.keys(null)jette le TypeErrormentionné. Pour résoudre ce problème, utilisez if(obj === null) {return null}- sans les qoutes autour null.
veproza
1
Autre problème: votre code ne gère pas la possibilité d'incorporer des "caractères dans des chaînes.
Pointy
@Pointy - oui, je vais devoir ajouter une logique pour cela ... merci
zahabba

Réponses:

131

Réponse générique

Cette erreur se produit lorsque vous appelez une fonction qui attend un objet comme argument, mais qui transmet à la place undefined ou null , comme par exemple

Object.keys(null)
Object.assign(window.UndefinedVariable, {})

Comme c'est généralement par erreur, la solution est de vérifier votre code et de corriger la condition null / indéfinie afin que la fonction obtienne un objet approprié ou ne soit pas appelée du tout.

Object.keys({'key': 'value'})
if (window.UndefinedVariable) {
    Object.assign(window.UndefinedVariable, {})
}

Réponse spécifique au code en question

La ligne if (obj === 'null') { return null;} // null unchanged ne sera pas évaluée lorsqu'elle est donnée null, seulement si la chaîne est donnée "null". Donc, si vous passez la nullvaleur réelle à votre script, elle sera analysée dans la partie Objet du code. Et Object.keys(null)jette le TypeErrormentionné. Pour résoudre ce problème, utilisez if(obj === null) {return null}- sans les qoutes autour de null.

Veproza
la source
8
Highlight: "Et Object.keys(null)jette le TypeErrormentionné."
falsarella
1
Pour ajouter un autre exemple courant où cela se produit: delete obj.propertyobj===null
Gio
4

Assurez-vous que l'objet de destination n'est pas vide ( nullou undefined).

Vous pouvez initialiser l'objet de destination avec un objet vide comme ci-dessous:

var destinationObj = {};

Object.assign(destinationObj, sourceObj);
Yuvraj Patil
la source
2

Ceci est très utile pour éviter les erreurs lors de l'accès aux propriétés d'objets nuls ou non définis.

null à un objet non défini

const obj = null;
const newObj = obj || undefined;
// newObj = undefined

undefined à un objet vide

const obj; 
const newObj = obj || {};
// newObj = {}     
// newObj.prop = undefined, but no error here

null à objet vide

const obj = null;
const newObj = obj || {};
// newObj = {}  
// newObj.prop = undefined, but no error here
Banzy
la source
0

J'ai résolu le même problème dans un projet React Native. Je l'ai résolu en utilisant ceci.

let data = snapshot.val();
if(data){
  let items = Object.values(data);
}
else{
  //return null
}
ziggybaba
la source
0

Dans mon cas, j'ai ajouté l'extension Lucid à ​​Chrome et je n'ai pas remarqué le problème à ce moment-là. Après environ une journée de travail sur le problème et de renversement du programme, dans un message, quelqu'un avait mentionné Lucid. Je me suis souvenu de ce que j'avais fait et j'ai supprimé l'extension de Chrome et j'ai de nouveau exécuté le programme. Le problème avait disparu. Je travaille avec React. J'ai pensé que cela pourrait aider.

Behzad Akbari
la source
0

Remplacer

if (typeof obj === 'undefined') { return undefined;} // return undefined for undefined
if (obj === 'null') { return null;} // null unchanged

avec

if (obj === undefined) { return undefined;} // return undefined for undefined 
if (obj === null) { return null;} // null unchanged
Gev
la source
0

Si vous utilisez Laravel , mon problème était dans le nom de ma Route. Au lieu:

Route::put('/reason/update', 'REASONController@update');

J'ai écrit:

Route::put('/reason/update', 'RESONController@update');

et quand j'ai corrigé le nom du contrôleur, le code fonctionnait!

Nicodemos dos Santos
la source
0

Dans mon cas, j'avais une paire de parenthèses supplémentaires ()

Au lieu de

export default connect(
  someVariable
)(otherVariable)()

Ça aurait du être

export default connect(
  someVariable
)(otherVariable)
Justice Bringer
la source
-2

J'ai le même problème avec un élément dans un formulaire Web. Donc, ce que j'ai fait pour le réparer, c'était valider. if (Object === 'null') faire quelque chose

Ivan Fernandez
la source