Como resolver TypeError: Não é possível converter indefinido ou nulo em objeto

92

Escrevi algumas funções que replicam efetivamente JSON.stringify (), convertendo uma gama de valores em versões stringificadas. Quando eu transporto meu código para JSBin e o executo em alguns valores de amostra, ele funciona perfeitamente. Mas estou recebendo este erro em um executor de especificações projetado para testar isso.

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

A mensagem de erro que estou recebendo do testador é:

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 falhar com: stringifyJSON (null) por exemplo

Zahabba
fonte
1
forneça a entrada para a qual você está recebendo o erro, pois está funcionando para stringifyJSON ({a: 'b', c: 'd'})
vinayakj
1
Além do erro, stringifyJSON([1,2,3])retorna 1,2,3e stringifyJSON({foo: 'bar'})retorna {foo: "bar"}, ambos os quais não são JSON válidos.
Felix Kling de
4
Meu palpite seria esta linha if (obj === 'null') { return null;} // null unchanged, - que não passará quando fornecida null, somente se for dada a string "null". Portanto, se você passar o nullvalor real para o seu script, ele será analisado na parte Object do código. E Object.keys(null)joga o TypeErrormencionado. Para consertar, use if(obj === null) {return null}- sem as perguntas ao redor null.
veproza
1
Outro problema: seu código não lida com a possibilidade de "caracteres embutidos em strings.
Pointy de
@Pointy - sim, vou precisar adicionar alguma lógica para isso ... obrigado
zahabba

Respostas:

134

Resposta genérica

Este erro é causado quando você chama uma função que espera um Object como seu argumento, mas passa undefined ou null em vez disso, como por exemplo

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

Como isso geralmente ocorre por engano, a solução é verificar seu código e corrigir a condição nulo / indefinido para que a função obtenha um objeto adequado ou não seja chamada de forma alguma.

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

Resposta específica para o código em questão

A linha if (obj === 'null') { return null;} // null unchanged não será avaliada quando fornecida null, apenas se fornecida a string "null". Portanto, se você passar o nullvalor real para o seu script, ele será analisado na parte Object do código. E Object.keys(null)joga o TypeErrormencionado. Para corrigir isso, use if(obj === null) {return null}- sem as perguntas ao redor de null.

veproza
fonte
8
Destaque: "E Object.keys(null)joga o TypeErrormencionado."
falsarella
1
Para adicionar outro exemplo comum onde isso acontece: delete obj.propertyondeobj===null
Gio
4

Certifique-se de que o objeto de destino não esteja vazio ( nullou undefined).

Você pode inicializar o objeto de destino com o objeto vazio como abaixo:

var destinationObj = {};

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

Isso é muito útil para evitar erros ao acessar propriedades de objetos nulos ou indefinidos.

objeto nulo para indefinido

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

indefinido para objeto vazio

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

objeto nulo para vazio

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

Resolvi o mesmo problema em um projeto React Native. Eu resolvi usando isso.

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

No meu caso, adicionei a extensão Lucid ao Chrome e não percebi o problema naquele momento. Após cerca de um dia trabalhando no problema e virando o programa de cabeça para baixo, em uma postagem, alguém mencionou a Lucid. Lembrei-me do que tinha feito e removi a extensão do Chrome e executei o programa novamente. O problema foi embora. Estou trabalhando com o React. Achei que isso pudesse ajudar.

Behzad Akbari
fonte
0

Substituir

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

com

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

Se você está usando o Laravel , meu problema estava no nome da minha Rota. Em vez de:

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

Eu escrevi:

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

e quando consertei o nome do controlador, o código funcionou!

Nicodemos dos Santos
fonte
0

No meu caso, eu tinha um par extra de parênteses ()

Ao invés de

export default connect(
  someVariable
)(otherVariable)()

Tinha que ser

export default connect(
  someVariable
)(otherVariable)
Justice Bringer
fonte
0

O trecho abaixo é suficiente para entender como encontrei o mesmo problema, mas em um cenário diferente e como resolvi usando a orientação na resposta aceita. No meu caso, eu estava tentando registrar as chaves do objeto presente no índice 0 do array 'defaultViewData' usando o método Object.keys ().

defaultViewData = [{"name": "DEFAULT_VIEW_PLP","value": {"MSH25": "LIST"}}] 

console.log('DEFAULT_VIEW', Object.keys(this.props.defaultViewData[0]));

O console.log não estava sendo impresso e eu estava recebendo o mesmo erro postado nesta pergunta. Para evitar esse erro, adicionei a condição abaixo

    if(this.props.defaultViewData[0]) {
  console.log('DEFAULT_VIEW', Object.keys(this.props.defaultViewData[0]));
}

Adicionar essa verificação garantiu que eu não recebesse esse erro. Espero que isso ajude alguém.

Nota: este é o código React.js. (embora para entender o problema não importe).

utkarsh-k
fonte
-2

Eu tenho o mesmo problema com um elemento em um formulário da web. Então o que fiz para consertar foi validar. if (Object === 'null') faça algo

Ivan Fernandez
fonte