Cómo resolver TypeError: no se puede convertir indefinido o nulo en objeto

90

Escribí un par de funciones que replican efectivamente JSON.stringify (), convirtiendo un rango de valores en versiones en cadena. Cuando transfiero mi código a JSBin y lo ejecuto en algunos valores de muestra, funciona bien. Pero recibo este error en un corredor de especificaciones diseñado para probar esto.

Mi código:

  // 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) + "";
    }
};

El mensaje de error que recibo del probador es:

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)

Parece fallar con: stringifyJSON (null) por ejemplo

zahabba
fuente
1
proporcione la entrada para la que está obteniendo el error, ya que funciona para stringifyJSON ({a: 'b', c: 'd'})
vinayakj
1
Aparte del error, stringifyJSON([1,2,3])devoluciones 1,2,3y stringifyJSON({foo: 'bar'})devoluciones {foo: "bar"}, las cuales no son JSON válidas.
Felix Kling
4
Mi conjetura sería esta línea if (obj === 'null') { return null;} // null unchanged, que no pasará cuando se proporcione null, solo si se le da la cadena "null". Entonces, si pasa el nullvalor real a su secuencia de comandos, se analizará en la parte Objeto del código. Y Object.keys(null)lanza lo TypeErrormencionado. Para solucionarlo, use if(obj === null) {return null}- sin las preguntas alrededor null.
veproza
1
Otro problema: su código no maneja la posibilidad de "caracteres incrustados en cadenas.
Puntiagudo
@Pointy - sí, tendré que agregar algo de lógica para eso ... gracias
zahabba

Respuestas:

131

Respuesta genérica

Este error se produce cuando llamas a una función que espera un Objeto como argumento, pero pasa undefined o null en su lugar, como por ejemplo

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

Como suele ser por error, la solución es verificar su código y corregir la condición nula / indefinida para que la función obtenga un objeto adecuado o no se llame en absoluto.

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

Respuesta específica al código en cuestión

La línea if (obj === 'null') { return null;} // null unchanged no se evaluará cuando se proporcione null, solo si se proporciona la cadena "null". Entonces, si pasa el nullvalor real a su secuencia de comandos, se analizará en la parte Objeto del código. Y Object.keys(null)lanza lo TypeErrormencionado. Para solucionarlo, use if(obj === null) {return null}- sin los qoutes alrededor de null.

veproza
fuente
8
Resaltar: "Y Object.keys(null)lanza lo TypeErrormencionado".
falsarella
1
Para agregar otro ejemplo común donde esto sucede: delete obj.propertydondeobj===null
Gio
4

Asegúrese de que el objeto de destino no esté vacío ( nullo undefined).

Puede inicializar el objeto de destino con un objeto vacío como se muestra a continuación:

var destinationObj = {};

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

Esto es muy útil para evitar errores al acceder a propiedades de objetos nulos o indefinidos.

nulo a objeto indefinido

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

indefinido a objeto vacío

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

nulo a objeto vacío

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

Resolví el mismo problema en un proyecto React Native. Lo resolví usando esto.

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

En mi caso, agregué la extensión Lucid a Chrome y no noté el problema en ese momento. Después de aproximadamente un día de trabajar en el problema y darle la vuelta al programa, en una publicación alguien había mencionado a Lucid. Recordé lo que había hecho, eliminé la extensión de Chrome y volví a ejecutar el programa. El problema desapareció. Estoy trabajando con React. Pensé que esto podría ayudar.

Behzad Akbari
fuente
0

Reemplazar

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

con

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

Si está usando Laravel , mi problema estaba en el nombre de mi ruta. En lugar:

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

Escribí:

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

y cuando arreglé el nombre del controlador, ¡el código funcionó!

Nicodemos dos Santos
fuente
0

En mi caso tenía un par de paréntesis extra ()

En vez de

export default connect(
  someVariable
)(otherVariable)()

Tenia que ser

export default connect(
  someVariable
)(otherVariable)
Portador de justicia
fuente
-2

Tengo el mismo problema con un elemento en un formulario web. Entonces, lo que hice para solucionarlo fue validar. si (Objeto === 'nulo') hacer algo

Iván Fernández
fuente