วิธีตรวจสอบว่าวัตถุ JavaScript เป็น JSON หรือไม่


91

ฉันมีออบเจ็กต์ JSON ที่ซ้อนกันซึ่งฉันต้องวนซ้ำและค่าของแต่ละคีย์อาจเป็นสตริงอาร์เรย์ JSON หรือออบเจ็กต์ JSON อื่น ขึ้นอยู่กับประเภทของวัตถุฉันจำเป็นต้องดำเนินการต่างๆ มีวิธีใดบ้างที่ฉันสามารถตรวจสอบประเภทของวัตถุเพื่อดูว่าเป็นสตริงออบเจ็กต์ JSON หรืออาร์เรย์ JSON

ฉันพยายามใช้typeofและinstanceofแต่ทั้งคู่ก็ไม่ได้ดูเหมือนจะทำงานตามที่typeofจะกลับวัตถุสำหรับทั้งวัตถุ JSON และอาร์เรย์และช่วยให้เกิดข้อผิดพลาดเมื่อฉันทำinstanceofobj instanceof JSON

เพื่อให้เจาะจงมากขึ้นหลังจากแยกวิเคราะห์ JSON เป็นออบเจ็กต์ JS มีวิธีใดบ้างที่ฉันสามารถตรวจสอบได้ว่าเป็นสตริงปกติหรือวัตถุที่มีคีย์และค่า (จากออบเจ็กต์ JSON) หรืออาร์เรย์ (จากอาร์เรย์ JSON )?

ตัวอย่างเช่น:

JSON

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

ตัวอย่าง JavaScript

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

ฉันจะตรวจสอบวัตถุดังที่แสดงด้านบนได้อย่างไร


3
JSONเป็นเพียงสัญกรณ์เก็บไว้เป็นสตริง แน่ใจหรือว่าไม่สับสนคำศัพท์?
zerkms

ไม่ฉันอัปเดตคำถามเพื่อให้ชัดเจนขึ้น ฉันเดาว่าคำถามหลักของฉันคือเกิดอะไรขึ้นหลังจากที่เรา.parse()สร้างสตริง JSON และจะระบุได้อย่างไร
Wei Hao

1
การเปลี่ยนแปลงไม่ได้ทำให้ชัดเจนมากขึ้น (สำหรับฉัน) จะเกิดอะไรขึ้นถ้าคุณยกตัวอย่าง JSON ที่คุณกำลังเผชิญอยู่
zerkms

อัปเดตคำถามพร้อมตัวอย่าง (:
Wei Hao

คำถามที่แท้จริงคือทำไมคุณถึงสนใจ?
Asherah

คำตอบ:


130

ฉันจะตรวจสอบแอตทริบิวต์ตัวสร้าง

เช่น

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

แก้ไข: เพิ่มการตรวจสอบค่าว่างและการตรวจสอบที่ไม่ได้กำหนด


9
else ifไม่จำเป็น
McSonk

ไม่เหมือนกับการใช้ instanceof หรือไม่? developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
Pereira

@Pereira: JavaScript มีริ้วรอยที่สับสน ลองใช้อินสแตนซ์สตริงอินสแตนซ์
Programming Guy

{}.constructorทำให้ฉันเข้าสู่ERROR TypeError: Cannot read property 'constructor' of undefinedแอปพลิเคชันเชิงมุมของฉัน
kebab-case

1
ifงบเยอะ... ใช้กswitch!
Nanoo

26

คุณสามารถใช้Array.isArrayเพื่อตรวจสอบอาร์เรย์ จากนั้นtypeof obj == 'สตริง'และtypeof obj == 'วัตถุ'

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' คือสตริง
'a' คืออาร์เรย์
'o' คือ object
'i' คืออื่น ๆ


5
อย่าลืมคำนึงถึงสิ่งนั้นด้วยtypeof null === 'object'
hugomg

[{ "name":[ {"key": "any key" } ] }] นี่เป็น json ที่ถูกต้องเช่นกัน แต่ส่งคืนอาร์เรย์ด้วยรหัสของคุณ ตรวจสอบสิ่งนี้ - ซอ
Sudhir K Gupta

17

วัตถุ JSON คือวัตถุ หากต้องการตรวจสอบว่าชนิดเป็นประเภทวัตถุหรือไม่ให้ประเมินคุณสมบัติตัวสร้าง

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

เช่นเดียวกับประเภทอื่น ๆ ทั้งหมด:

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
ทรัพยากรที่เข้ารหัส JSON ไม่ใช่วัตถุ มันเป็นสตริง หลังจากที่คุณถอดรหัสหรือใน Javascript JSON.parse()เท่านั้นทรัพยากร JSON จะกลายเป็นวัตถุ ดังนั้นหากคุณทดสอบทรัพยากรที่มาจากเซิร์ฟเวอร์เพื่อดูว่าเป็น JSON หรือไม่ควรตรวจสอบ String ก่อนจากนั้นถ้าไม่ใช่ a <empty string>แล้วจึงแยกวิเคราะห์ว่าเป็นวัตถุหรือไม่
Hmerman6006

8

หากคุณกำลังพยายามตรวจสอบประเภทของobjectหลังจากที่คุณแยกวิเคราะห์JSONสตริงฉันขอแนะนำให้ตรวจสอบแอตทริบิวต์ตัวสร้าง:

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

นี่จะเป็นการตรวจสอบที่เร็วกว่า typeof หรือ instanceof มาก

หากไลบรารี JSONไม่ส่งคืนอ็อบเจ็กต์ที่สร้างด้วยฟังก์ชันเหล่านี้ฉันจะสงสัยอย่างมาก


แนวทางที่ตรงกว่ามาก ขอบคุณ! = D
Eduardo Lucio

คำตอบที่ต้องการ คุณจะได้รับข้อมูลประโยชน์ด้านประสิทธิภาพจากที่ใด
Daniel F

@DanielF มันเป็นภูมิปัญญาทั่วไปใน '12 ตอนนี้ทุกอย่างแตกต่างกันไปดังนั้นฉันจึงไม่รู้ว่ามันถือหรือไม่
JoshRagem

5

คุณสามารถสร้างตัวสร้างของคุณเองสำหรับการแยกวิเคราะห์ JSON:

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

จากนั้นตรวจสอบอินสแตนซ์เพื่อดูว่าจำเป็นต้องแยกวิเคราะห์ในตอนแรกหรือไม่

test instanceof JSONObj

5

คำตอบโดย @PeterWilkinson ไม่ได้ผลสำหรับฉันเพราะตัวสร้างสำหรับออบเจ็กต์ที่ "พิมพ์" ได้รับการปรับแต่งตามชื่อของวัตถุนั้น ฉันต้องทำงานกับtypeof

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

4

ฉันเขียนโมดูล npm เพื่อแก้ปัญหานี้ มีให้ที่นี่ :

object-types: โมดูลสำหรับค้นหาประเภทตามตัวอักษรที่อยู่ภายใต้วัตถุ

ติดตั้ง

  npm install --save object-types


การใช้งาน

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

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

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

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

ลองดูมันน่าจะแก้ปัญหาของคุณได้ โปรดแจ้งให้เราทราบหากคุณมีคำถามใด ๆ https://github.com/dawsonbotsford/object-types


2

คุณยังสามารถลองแยกวิเคราะห์ข้อมูลแล้วตรวจสอบว่าคุณมีวัตถุหรือไม่:

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

2

ฉันรวมตัวดำเนินการ typeof เข้ากับการตรวจสอบแอตทริบิวต์ตัวสร้าง (โดย 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'));
});

ผลลัพธ์:

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

ทำไมไม่ตรวจสอบ Number - สั้นกว่าเล็กน้อยและใช้งานได้ใน 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

ฉันรู้ว่านี่เป็นคำถามเก่ามากพร้อมคำตอบที่ดี อย่างไรก็ตามดูเหมือนว่ายังสามารถเพิ่ม 2 ¢ของฉันลงไปได้

สมมติว่าคุณกำลังพยายามทดสอบไม่ใช่ออบเจ็กต์ JSON แต่เป็นสตริงที่จัดรูปแบบเป็น JSON (ซึ่งดูเหมือนจะเป็นกรณีของคุณvar data) คุณสามารถใช้ฟังก์ชันต่อไปนี้ที่ส่งคืนบูลีน (เป็นหรือไม่ใช่ ' 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
  }

}

นี่คือตัวอย่างบางส่วนของการใช้ฟังก์ชันด้านบน:

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 -----------------
abc false

2 -----------------
{"abc": "def"} true

3 -----------------
{"abc": "def} false

4 -----------------
{} true

5 -----------------
[{}] true

6 -----------------
[{},] false

7 -----------------
[{"a":1, "b":   2}, {"c":3}] true

โปรดลองใช้ตัวอย่างข้อมูลด้านล่างและแจ้งให้เราทราบว่าสิ่งนี้เหมาะกับคุณหรือไม่ :)

สำคัญ: ฟังก์ชันที่นำเสนอในโพสต์นี้ดัดแปลงมาจากhttps://airbrake.io/blog/javascript-error-handling/syntaxerror-json-parse-bad-parsingซึ่งคุณสามารถค้นหารายละเอียดเพิ่มเติมและน่าสนใจเกี่ยวกับ JSON.parse ( ) ฟังก์ชัน

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

ลองทำตามนี้

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

ใช้งานได้ดังตัวอย่างด้านล่าง

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

คำตอบของปีเตอร์พร้อมเช็คเพิ่มเติม! รับรองไม่หายแน่นอน 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

อ้างอิงจากคำตอบของ @Martin Wantke แต่มีการปรับปรุง / ปรับเปลี่ยนที่แนะนำ ...

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

}

หมายเหตุ:ฉันพบว่าแนวทางนี้สอนได้ดีมากดังนั้นฉันจึงส่งคำตอบนี้


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.