Eu tenho um objeto JSON aninhado que preciso percorrer, e o valor de cada chave pode ser uma String, matriz JSON ou outro objeto JSON. Dependendo do tipo de objeto, preciso realizar diferentes operações. Existe alguma maneira de verificar o tipo do objeto para ver se é uma String, objeto JSON ou array JSON?
Tentei usar typeof
e, instanceof
mas os dois não parecem funcionar, pois typeof
retornará um objeto para o objeto JSON e para o array e instanceof
dará um erro ao fazer isso obj instanceof JSON
.
Para ser mais específico, depois de analisar o JSON em um objeto JS, há alguma maneira de verificar se é uma string normal, ou um objeto com chaves e valores (de um objeto JSON), ou uma matriz (de uma matriz JSON )?
Por exemplo:
JSON
var data = "{'hi':
{'hello':
['hi1','hi2']
},
'hey':'words'
}";
JavaScript de amostra
var jsonObj = JSON.parse(data);
var path = ["hi","hello"];
function check(jsonObj, path) {
var parent = jsonObj;
for (var i = 0; i < path.length-1; i++) {
var key = path[i];
if (parent != undefined) {
parent = parent[key];
}
}
if (parent != undefined) {
var endLength = path.length - 1;
var child = parent[path[endLength]];
//if child is a string, add some text
//if child is an object, edit the key/value
//if child is an array, add a new element
//if child does not exist, add a new key/value
}
}
Como faço a verificação do objeto conforme mostrado acima?
fonte
.parse()
em uma string JSON e como identificá-lo?Respostas:
Eu verificaria o atributo construtor.
por exemplo
var stringConstructor = "test".constructor; var arrayConstructor = [].constructor; var objectConstructor = ({}).constructor; function whatIsIt(object) { if (object === null) { return "null"; } if (object === undefined) { return "undefined"; } if (object.constructor === stringConstructor) { return "String"; } if (object.constructor === arrayConstructor) { return "Array"; } if (object.constructor === objectConstructor) { return "Object"; } { return "don't know"; } } var testSubjects = ["string", [1,2,3], {foo: "bar"}, 4]; for (var i=0, len = testSubjects.length; i < len; i++) { alert(whatIsIt(testSubjects[i])); }
Editar: Adicionada uma verificação nula e uma verificação indefinida.
fonte
else if
é desnecessário{}.constructor
está fazendo com que eu entreERROR TypeError: Cannot read property 'constructor' of undefined
no meu aplicativo angular.Você pode usar Array.isArray para verificar os arrays. Então typeof obj == 'string' , e typeof obj == 'object' .
var s = 'a string', a = [], o = {}, i = 5; function getType(p) { if (Array.isArray(p)) return 'array'; else if (typeof p == 'string') return 'string'; else if (p != null && typeof p == 'object') return 'object'; else return 'other'; } console.log("'s' is " + getType(s)); console.log("'a' is " + getType(a)); console.log("'o' is " + getType(o)); console.log("'i' is " + getType(i));
fonte
typeof null === 'object'
[{ "name":[ {"key": "any key" } ] }]
isso também é json válido, mas seu array de retorno pelo seu código. verifique isso - violinoUm objeto JSON é um objeto. Para verificar se um tipo é um tipo de objeto, avalie a propriedade constructor.
function isObject(obj) { return obj !== undefined && obj !== null && obj.constructor == Object; }
O mesmo se aplica a todos os outros tipos:
function isArray(obj) { return obj !== undefined && obj !== null && obj.constructor == Array; } function isBoolean(obj) { return obj !== undefined && obj !== null && obj.constructor == Boolean; } function isFunction(obj) { return obj !== undefined && obj !== null && obj.constructor == Function; } function isNumber(obj) { return obj !== undefined && obj !== null && obj.constructor == Number; } function isString(obj) { return obj !== undefined && obj !== null && obj.constructor == String; } function isInstanced(obj) { if(obj === undefined || obj === null) { return false; } if(isArray(obj)) { return false; } if(isBoolean(obj)) { return false; } if(isFunction(obj)) { return false; } if(isNumber(obj)) { return false; } if(isObject(obj)) { return false; } if(isString(obj)) { return false; } return true; }
fonte
JSON.parse()
é que o recurso JSON se torna um objeto. Portanto, se você testar um recurso proveniente de um servidor para ver se é JSON, é melhor verificar primeiro se há String, se não é um<empty string>
e, depois de analisar, se é um objeto.Se você estiver tentando verificar o tipo de an
object
depois de analisar umaJSON
string, sugiro verificar o atributo do construtor:obj.constructor == Array || obj.constructor == String || obj.constructor == Object
Essa será uma verificação muito mais rápida do que typeof ou instanceof.
Se uma biblioteca JSON não retornar objetos construídos com essas funções, eu suspeitaria muito dela.
fonte
A resposta de @PeterWilkinson não funcionou para mim porque um construtor para um objeto "digitado" é personalizado para o nome desse objeto. Eu tive que trabalhar com typeof
function isJson(obj) { var t = typeof obj; return ['boolean', 'number', 'string', 'symbol', 'function'].indexOf(t) == -1; }
fonte
Você pode fazer seu próprio construtor para análise JSON:
var JSONObj = function(obj) { $.extend(this, JSON.parse(obj)); } var test = new JSONObj('{"a": "apple"}'); //{a: "apple"}
Em seguida, verifique instanceof para ver se precisava de análise originalmente
test instanceof JSONObj
fonte
Escrevi um módulo npm para resolver esse problema. Está disponível aqui :
object-types
: um módulo para descobrir quais tipos literais estão subjacentes aos objetosInstalar
Uso
const objectTypes = require('object-types'); objectTypes({}); //=> 'object' objectTypes([]); //=> 'array' objectTypes(new Object(true)); //=> 'boolean'
Dê uma olhada, deve resolver exatamente o seu problema. Deixe-me saber se você tiver alguma dúvida! https://github.com/dawsonbotsford/object-types
fonte
você também pode tentar analisar os dados e, em seguida, verificar se obteve o objeto:
var testIfJson = JSON.parse(data); if (typeOf testIfJson == "object") { //Json } else { //Not Json }
fonte
Eu combino o operador typeof com uma verificação do atributo construtor (por Peter):
var typeOf = function(object) { var firstShot = typeof object; if (firstShot !== 'object') { return firstShot; } else if (object.constructor === [].constructor) { return 'array'; } else if (object.constructor === {}.constructor) { return 'object'; } else if (object === null) { return 'null'; } else { return 'don\'t know'; } } // Test var testSubjects = [true, false, 1, 2.3, 'string', [4,5,6], {foo: 'bar'}, null, undefined]; console.log(['typeOf()', 'input parameter'].join('\t')) console.log(new Array(28).join('-')); testSubjects.map(function(testSubject){ console.log([typeOf(testSubject), JSON.stringify(testSubject)].join('\t\t')); });
Resultado:
typeOf() input parameter --------------------------- boolean true boolean false number 1 number 2.3 string "string" array [4,5,6] object {"foo":"bar"} null null undefined
fonte
Eu sei que esta é uma pergunta muito antiga com boas respostas. No entanto, parece que ainda é possível adicionar meus 2 centavos a ele.
Supondo que você esteja tentando testar não um objeto JSON em si, mas uma String formatada como JSON (o que parece ser o caso no seu
var data
), você poderia usar a seguinte função que retorna um booleano (é ou não é um ' JSON '):function isJsonString( jsonString ) { // This function below ('printError') can be used to print details about the error, if any. // Please, refer to the original article (see the end of this post) // for more details. I suppressed details to keep the code clean. // let printError = function(error, explicit) { console.log(`[${explicit ? 'EXPLICIT' : 'INEXPLICIT'}] ${error.name}: ${error.message}`); } try { JSON.parse( jsonString ); return true; // It's a valid JSON format } catch (e) { return false; // It's not a valid JSON format } }
Aqui estão alguns exemplos de uso da função acima:
console.log('\n1 -----------------'); let j = "abc"; console.log( j, isJsonString(j) ); console.log('\n2 -----------------'); j = `{"abc": "def"}`; console.log( j, isJsonString(j) ); console.log('\n3 -----------------'); j = '{"abc": "def}'; console.log( j, isJsonString(j) ); console.log('\n4 -----------------'); j = '{}'; console.log( j, isJsonString(j) ); console.log('\n5 -----------------'); j = '[{}]'; console.log( j, isJsonString(j) ); console.log('\n6 -----------------'); j = '[{},]'; console.log( j, isJsonString(j) ); console.log('\n7 -----------------'); j = '[{"a":1, "b": 2}, {"c":3}]'; console.log( j, isJsonString(j) );
Ao executar o código acima, você obterá os seguintes resultados:
1 ----------------- abc false 2 ----------------- {"abc": "def"} true 3 ----------------- {"abc": "def} false 4 ----------------- {} true 5 ----------------- [{}] true 6 ----------------- [{},] false 7 ----------------- [{"a":1, "b": 2}, {"c":3}] true
Por favor, tente o snippet abaixo e diga-nos se isso funciona para você. :)
IMPORTANTE: a função apresentada nesta postagem foi adaptada de https://airbrake.io/blog/javascript-error-handling/syntaxerror-json-parse-bad-parsing onde você pode encontrar mais detalhes interessantes sobre o JSON.parse ( ) função.
function isJsonString( jsonString ) { let printError = function(error, explicit) { console.log(`[${explicit ? 'EXPLICIT' : 'INEXPLICIT'}] ${error.name}: ${error.message}`); } try { JSON.parse( jsonString ); return true; // It's a valid JSON format } catch (e) { return false; // It's not a valid JSON format } } console.log('\n1 -----------------'); let j = "abc"; console.log( j, isJsonString(j) ); console.log('\n2 -----------------'); j = `{"abc": "def"}`; console.log( j, isJsonString(j) ); console.log('\n3 -----------------'); j = '{"abc": "def}'; console.log( j, isJsonString(j) ); console.log('\n4 -----------------'); j = '{}'; console.log( j, isJsonString(j) ); console.log('\n5 -----------------'); j = '[{}]'; console.log( j, isJsonString(j) ); console.log('\n6 -----------------'); j = '[{},]'; console.log( j, isJsonString(j) ); console.log('\n7 -----------------'); j = '[{"a":1, "b": 2}, {"c":3}]'; console.log( j, isJsonString(j) );
fonte
Tente isto
if ( typeof is_json != "function" ) function is_json( _obj ) { var _has_keys = 0 ; for( var _pr in _obj ) { if ( _obj.hasOwnProperty( _pr ) && !( /^\d+$/.test( _pr ) ) ) { _has_keys = 1 ; break ; } } return ( _has_keys && _obj.constructor == Object && _obj.constructor != Array ) ? 1 : 0 ; }
Funciona para o exemplo abaixo
var _a = { "name" : "me", "surname" : "I", "nickname" : { "first" : "wow", "second" : "super", "morelevel" : { "3level1" : 1, "3level2" : 2, "3level3" : 3 } } } ; var _b = [ "name", "surname", "nickname" ] ; var _c = "abcdefg" ; console.log( is_json( _a ) ); console.log( is_json( _b ) ); console.log( is_json( _c ) );
fonte
Por que não verificar o número - um pouco mais curto e funciona em IE / Chrome / FF / node.js
function whatIsIt(object) { if (object === null) { return "null"; } else if (object === undefined) { return "undefined"; } if (object.constructor.name) { return object.constructor.name; } else { // last chance 4 IE: "\nfunction Number() {\n [native code]\n}\n" / node.js: "function String() { [native code] }" var name = object.constructor.toString().split(' '); if (name && name.length > 1) { name = name[1]; return name.substr(0, name.indexOf('(')); } else { // unreachable now(?) return "don't know"; } } } var testSubjects = ["string", [1,2,3], {foo: "bar"}, 4]; // Test all options console.log(whatIsIt(null)); console.log(whatIsIt()); for (var i=0, len = testSubjects.length; i < len; i++) { console.log(whatIsIt(testSubjects[i])); }
fonte
A resposta de Pedro com uma verificação adicional! Claro, não 100% garantido!
var isJson = false; outPutValue = "" var objectConstructor = {}.constructor; if(jsonToCheck.constructor === objectConstructor){ outPutValue = JSON.stringify(jsonToCheck); try{ JSON.parse(outPutValue); isJson = true; }catch(err){ isJson = false; } } if(isJson){ alert("Is json |" + JSON.stringify(jsonToCheck) + "|"); }else{ alert("Is other!"); }
fonte
tente desse jeito sujo
('' + obj).includes('{')
fonte