Come verificare se l'oggetto JavaScript è JSON


91

Ho un oggetto JSON nidificato che devo scorrere e il valore di ciascuna chiave potrebbe essere una stringa, un array JSON o un altro oggetto JSON. A seconda del tipo di oggetto, devo eseguire diverse operazioni. C'è un modo per controllare il tipo di oggetto per vedere se è una stringa, un oggetto JSON o un array JSON?

Ho provato a usare typeofe instanceofma entrambi non sembravano funzionare, poiché typeofrestituirà un oggetto sia per l'oggetto JSON che per l'array e instanceofrestituisce un errore quando lo faccio obj instanceof JSON.

Per essere più precisi, dopo aver analizzato il JSON in un oggetto JS, esiste un modo per verificare se si tratta di una stringa normale o di un oggetto con chiavi e valori (da un oggetto JSON) o un array (da un array JSON )?

Per esempio:

JSON

var data = "{'hi':
             {'hello':
               ['hi1','hi2']
             },
            'hey':'words'
           }";

JavaScript di esempio

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
    }
}

Come si esegue il controllo dell'oggetto come mostrato sopra?


3
JSON è solo una notazione memorizzata come stringa . Sei sicuro di non confondere i termini?
zerkms

No, ho aggiornato la domanda per renderla più chiara. Immagino che la mia domanda principale sia cosa succede dopo aver eseguito un .parse()su una stringa JSON e come identificarlo?
Wei Hao

1
il cambiamento non lo ha reso più chiaro (almeno per me). E se fornisci un esempio di JSON con cui hai a che fare
zerkms

Domanda aggiornata con un esempio. (:
Wei Hao

La vera domanda è: perché ti interessa?
Asherah

Risposte:


130

Controllerei l'attributo del costruttore.

per esempio

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]));
}

Modifica: aggiunto un controllo nullo e un controllo non definito.


9
else ifnon è necessario
McSonk

Non è la stessa cosa che usare instanceof? developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
Pereira

@ Pereira: JavaScript ha alcune rughe confuse. Prova "sure_this_is_a_string" instanceof String.
Programming Guy

{}.constructormi sta facendo entrare ERROR TypeError: Cannot read property 'constructor' of undefinednella mia applicazione angolare.
kebab-case

1
Così tante ifaffermazioni ... Usa un switch!
Nanoo

26

È possibile utilizzare Array.isArray per verificare la presenza di array. Quindi 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));

's' è una stringa
'a' è un array
'o' è l'oggetto
'i' è altro


5
Non dimenticare di tenerne contotypeof null === 'object'
hugomg

[{ "name":[ {"key": "any key" } ] }] anche questo è json valido ma il suo array di ritorno dal codice. controlla questo - violino
Sudhir K Gupta

17

Un oggetto JSON è un oggetto. Per verificare se un tipo è un tipo di oggetto, valutare la proprietà del costruttore.

function isObject(obj)
{
    return obj !== undefined && obj !== null && obj.constructor == Object;
}

Lo stesso vale per tutti gli altri tipi:

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;
}

3
La risorsa codificata JSON non è un oggetto. È una stringa. Solo dopo averlo decodificato o in Javascript JSON.parse(), la risorsa JSON diventa un oggetto. Pertanto, se provi una risorsa proveniente da un server per vedere se è JSON, è meglio controllare prima per String, poi se è non a <empty string>e poi dopo l'analisi se è un oggetto.
Hmerman6006

8

Se stai cercando di controllare il tipo di un objectdopo aver analizzato una JSONstringa, ti suggerisco di controllare l'attributo del costruttore:

obj.constructor == Array || obj.constructor == String || obj.constructor == Object

Questo sarà un controllo molto più veloce di typeof o instanceof.

Se una libreria JSON non restituisce oggetti costruiti con queste funzioni, ne sarei molto sospettoso.


Un approccio molto più diretto. Grazie! = D
Eduardo Lucio

Risposta preferita. Da dove prendi le informazioni sui vantaggi in termini di prestazioni?
Daniel F

@DanielF era saggezza comune nel '12, le cose sono tutte diverse ora, quindi non so se questo vale
JoshRagem

5

Potresti creare il tuo costruttore per l'analisi JSON:

var JSONObj = function(obj) { $.extend(this, JSON.parse(obj)); }
var test = new JSONObj('{"a": "apple"}');
//{a: "apple"}

Quindi controlla instanceof per vedere se aveva bisogno di essere analizzato originariamente

test instanceof JSONObj

5

La risposta di @PeterWilkinson non ha funzionato per me perché un costruttore per un oggetto "digitato" è personalizzato in base al nome di quell'oggetto. Ho dovuto lavorare con typeof

function isJson(obj) {
    var t = typeof obj;
    return ['boolean', 'number', 'string', 'symbol', 'function'].indexOf(t) == -1;
}

4

Ho scritto un modulo npm per risolvere questo problema. È disponibile qui :

object-types: un modulo per trovare quali tipi letterali sottostanno agli oggetti

Installare

  npm install --save object-types


Utilizzo

const objectTypes = require('object-types');

objectTypes({});
//=> 'object'

objectTypes([]);
//=> 'array'

objectTypes(new Object(true));
//=> 'boolean'

Dai un'occhiata, dovrebbe risolvere il tuo problema esatto. Fatemi sapere se avete domande! https://github.com/dawsonbotsford/object-types


2

puoi anche provare ad analizzare i dati e quindi controllare se hai oggetto:

var testIfJson = JSON.parse(data);
if (typeOf testIfJson == "object")
{
//Json
}
else
{
//Not Json
}

2

Combino l'operatore typeof con un controllo dell'attributo del costruttore (di 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'));
});

Risultato:

typeOf()    input parameter
---------------------------
boolean     true
boolean     false
number      1
number      2.3
string      "string"
array       [4,5,6]
object      {"foo":"bar"}
null        null
undefined       

2

Perché non controllare Numero: un po 'più corto e funziona in 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]));
}


2

So che questa è una domanda molto vecchia con buone risposte. Tuttavia, sembra che sia ancora possibile aggiungere il mio 2 ¢ ad esso.

Supponendo che tu stia tentando di testare non un oggetto JSON in sé ma una stringa formattata come JSON (che sembra essere il tuo caso var data), potresti usare la seguente funzione che restituisce un booleano (è o non è un ' 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
  }

}

Ecco alcuni esempi di utilizzo della funzione sopra:

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) );

Quando esegui il codice sopra, otterrai i seguenti risultati:

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

Per favore, prova lo snippet di seguito e facci sapere se funziona per te. :)

IMPORTANTE: la funzione presentata in questo post è stata adattata da https://airbrake.io/blog/javascript-error-handling/syntaxerror-json-parse-bad-parsing dove puoi trovare ulteriori e interessanti dettagli sul JSON.parse ( ) funzione.

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) );


1

Prova questo

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 ;
}

Funziona per l'esempio seguente

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 ) );

0

La risposta di Peter con un controllo aggiuntivo! Ovviamente non garantito al 100%!

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

0

Basato sulla risposta di @Martin Wantke, ma con alcuni miglioramenti / aggiustamenti consigliati ...

// NOTE: Check JavaScript type. By Questor
function getJSType(valToChk) {

    function isUndefined(valToChk) { return valToChk === undefined; }
    function isNull(valToChk) { return valToChk === null; }
    function isArray(valToChk) { return valToChk.constructor == Array; }
    function isBoolean(valToChk) { return valToChk.constructor == Boolean; }
    function isFunction(valToChk) { return valToChk.constructor == Function; }
    function isNumber(valToChk) { return valToChk.constructor == Number; }
    function isString(valToChk) { return valToChk.constructor == String; }
    function isObject(valToChk) { return valToChk.constructor == Object; }

    if(isUndefined(valToChk)) { return "undefined"; }
    if(isNull(valToChk)) { return "null"; }
    if(isArray(valToChk)) { return "array"; }
    if(isBoolean(valToChk)) { return "boolean"; }
    if(isFunction(valToChk)) { return "function"; }
    if(isNumber(valToChk)) { return "number"; }
    if(isString(valToChk)) { return "string"; }
    if(isObject(valToChk)) { return "object"; }

}

NOTA: ho trovato questo approccio molto didattico, quindi ho inviato questa risposta.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.