ฉันจะตรวจสอบว่าค่าเป็นวัตถุ json ได้อย่างไร


101

รหัสฝั่งเซิร์ฟเวอร์ของฉันส่งคืนค่าซึ่งเป็นวัตถุ json เมื่อสำเร็จและสตริง 'เท็จ' เมื่อเกิดความล้มเหลว ตอนนี้ฉันจะตรวจสอบได้อย่างไรว่าค่าที่ส่งคืนเป็นวัตถุ json


2
หากเป็นโค้ดฝั่งเซิร์ฟเวอร์ "ของคุณ" จริงทำไมไม่มีฟิลด์สถานะในผลลัพธ์ JSON แทนที่จะสร้างสถานการณ์ "บางครั้งก็เป็น JSON และบางครั้งก็ไม่ใช่" ... ?
HostileFork บอกว่าอย่าไว้วางใจใน

@Hostile สำหรับเหตุผลในการดีบัก ตอนนี้คุณไม่เคยเกิดความล้มเหลวแบบไหนที่เซิร์ฟเวอร์จะโยนและ ณ จุดนั้นไม่ได้ใช้ json
bart

1
ฉันยังไม่เห็นว่าการมีรหัสข้อผิดพลาด (เป็นช่องที่ระบุชื่อ) ในการตอบสนองของเซิร์ฟเวอร์จะทำลายสิ่งนั้นได้อย่างไร มันดีพอสำหรับ Freebase! wiki.freebase.com/wiki/MQL_errors
HostileFork บอกว่าอย่าไว้วางใจใน

โปรดเปลี่ยนคำตอบที่ยอมรับเป็นของ Serguei Federov หากคุณสามารถตอบได้ว่าคำตอบที่ยอมรับในปัจจุบันนั้นไม่ถูกต้อง
Serj Sagan

"วัตถุ json" คืออะไร? มีสตริง JSON และออบเจ็กต์ JS แต่ไม่มีสิ่งที่เรียกว่า "JavaScript Object Notation object"
mpen

คำตอบ:


106

jQuery.parseJSON () ควรส่งคืนวัตถุประเภท "object" ถ้าสตริงเป็น JSON ดังนั้นคุณจะต้องตรวจสอบประเภทด้วย typeof

var response=jQuery.parseJSON('response from server');
if(typeof response =='object')
{
  // It is JSON
}
else
{
  if(response ===false)
  {
     // the response was a string "false", parseJSON will convert it to boolean false
  }
  else
  {
    // the response was something else
  }
}

29
อาจจำเป็นต้องใช้ try / catch สำหรับข้อยกเว้นหากเป็นไปได้ว่า parseJSON จะจัดการกับสิ่งอื่นที่ไม่ใช่ค่า JSON (เช่น HTML)
acorncom

2
ก่อนหน้า jQuery 1.9 $ .parseJSON ส่งคืนค่า null แทนที่จะส่งข้อผิดพลาดหากส่งผ่านสตริงว่างค่าว่างหรือไม่ได้กำหนดแม้ว่าสิ่งเหล่านี้จะไม่ใช่ JSON ที่ถูกต้องก็ตาม ลิงค์เว็บไซต์ jquery
gloomy.penguin

7
วิธีนี้ไม่ใช่วิธีที่ดีที่สุดเนื่องจาก"SyntaxError: JSON.parse: unexpected character"ข้อผิดพลาดในการส่งคืน! ฉันคิดว่าทางออกที่ดีที่สุดคือใช้ try / catch ที่กล่าวโดยSerguei Fedorovในที่นี่: stackoverflow.com/questions/4295386/…
Nabi KAZ

2
หากคุณไม่ต้องการใช้ jquery คุณสามารถใช้ vanilla JS โดยตรวจสอบประเภทตัวสร้างตามที่อธิบายไว้ที่นี่: stackoverflow.com/questions/11182924/…
Mat

2
คำตอบนี้ไม่ถูกต้องคำตอบของ Serguei Federov ควรเป็นคำตอบที่ยอมรับได้
Serj Sagan

148

วิธีแก้ปัญหาที่เลือกใช้ไม่ได้ผลสำหรับฉันเพราะฉันได้รับไฟล์

     "Unexpected Token <" 

ข้อผิดพลาดใน Chrome เนื่องจากข้อผิดพลาดเกิดขึ้นทันทีที่มีการแยกวิเคราะห์และอักขระที่ไม่รู้จัก อย่างไรก็ตามมีวิธีแก้ปัญหานี้หากคุณส่งคืนเฉพาะค่าสตริงผ่าน ajax (ซึ่งมีประโยชน์พอสมควรหากคุณใช้ PHP หรือ ASPX เพื่อประมวลผลคำขอ ajax และอาจส่งคืน JSON หรือไม่ก็ได้ขึ้นอยู่กับเงื่อนไข)

วิธีแก้ปัญหานั้นค่อนข้างง่ายคุณสามารถทำสิ่งต่อไปนี้เพื่อตรวจสอบว่าเป็นการส่งคืน JSON ที่ถูกต้องหรือไม่

       var IS_JSON = true;
       try
       {
               var json = $.parseJSON(msg);
       }
       catch(err)
       {
               IS_JSON = false;
       }                

ดังที่ฉันได้กล่าวไปแล้วนี่เป็นวิธีแก้ปัญหาหากคุณกำลังส่งคืนรายการประเภทสตริงจากคำขอ AJAX ของคุณหรือหากคุณส่งคืนประเภทผสม


คำถามไม่ได้เกี่ยวกับสตริงที่ไม่ใช่ JSON แต่อย่างใด เซิร์ฟเวอร์ส่งคืนJSON ที่ถูกต้องเสมอ (สตริงfalseเป็น JSON ที่ถูกต้องด้วย) คำถามเป็นเพียงประเด็นเดียว: จะแยกความแตกต่างได้อย่างไรว่าสตริง JSON ที่แยกวิเคราะห์เป็นบูลีนfalseหรือวัตถุ
ดร

2
การพิจารณาประสิทธิภาพ: การห่อสิ่งนี้ในฟังก์ชันตรวจสอบให้แน่ใจว่าไม่ได้แยกวิเคราะห์ json สองครั้ง (ครั้งเดียวใน try catch และอีกครั้งในรหัสที่เรียกใช้ฟังก์ชัน)
Michiel Cornille

มันเป็นผู้ช่วยทำงานisJSON ()isJSON(someValue)ที่คุณสามารถใช้:
Chofoteddy

19

โซลูชันที่ 3 (วิธีที่เร็วที่สุด)

/**
 * @param Object
 * @returns boolean
 */
function isJSON (something) {
    if (typeof something != 'string')
        something = JSON.stringify(something);

    try {
        JSON.parse(something);
        return true;
    } catch (e) {
        return false;
    }
}

คุณสามารถใช้:

var myJson = [{"user":"chofoteddy"}, {"user":"bart"}];
isJSON(myJson); // true

วิธีที่ดีที่สุดในการตรวจสอบว่าวัตถุเป็นประเภท JSON หรืออาร์เรย์มีดังนี้:

var a = [],
    o = {};

โซลูชันที่ 1

toString.call(o) === '[object Object]'; // true
toString.call(a) === '[object Array]'; // true

โซลูชันที่ 2

a.constructor.name === 'Array'; // true
o.constructor.name === 'Object'; // true

แต่พูดอย่างเคร่งครัดอาร์เรย์เป็นส่วนหนึ่งของไวยากรณ์ JSON ดังนั้นสองตัวอย่างต่อไปนี้เป็นส่วนหนึ่งของการตอบสนอง JSON:

console.log(response); // {"message": "success"}
console.log(response); // {"user": "bart", "id":3}

และ:

console.log(response); // [{"user":"chofoteddy"}, {"user":"bart"}]
console.log(response); // ["chofoteddy", "bart"]

AJAX / JQuery (แนะนำ)

หากคุณใช้ JQuery เพื่อนำข้อมูลผ่าน AJAX ขอแนะนำให้คุณใส่แอตทริบิวต์ "dataType" เป็นค่า "json" ด้วยวิธีนี้หากคุณได้รับ JSON หรือไม่ JQuery จะตรวจสอบความถูกต้องให้คุณและทำให้ทราบผ่านฟังก์ชัน "success" และ "error" ตัวอย่าง:

$.ajax({
    url: 'http://www.something.com',
    data: $('#formId').serialize(),
    method: 'POST',
    dataType: 'json',
    // "sucess" will be executed only if the response status is 200 and get a JSON
    success: function (json) {},
    // "error" will run but receive state 200, but if you miss the JSON syntax
    error: function (xhr) {}
});

13

ถ้าคุณมี jQuery ใช้isPlainObject

if ($.isPlainObject(my_var)) {}

5
ถ้าคุณใช้ isPlainObject บนสตริงมันจะส่งคืนเท็จเช่น jQuery.isPlainObject ('{}')
Roy Shoa

ที่สำคัญหากมีไม่ใช่ JSON trueเหมือนค่าเป็นทรัพย์สินตามเอกสารฟังก์ชั่นนี้จะยังคงกลับมา
samvv

6
var checkJSON = function(m) {

   if (typeof m == 'object') { 
      try{ m = JSON.stringify(m); }
      catch(err) { return false; } }

   if (typeof m == 'string') {
      try{ m = JSON.parse(m); }
      catch (err) { return false; } }

   if (typeof m != 'object') { return false; }
   return true;

};


checkJSON(JSON.parse('{}'));      //true
checkJSON(JSON.parse('{"a":0}')); //true
checkJSON('{}');                  //true
checkJSON('{"a":0}');             //true
checkJSON('x');                   //false
checkJSON('');                    //false
checkJSON();                      //false

4

เนื่องจากเป็นวัตถุเท็จและวัตถุ json ทำไมคุณไม่ตรวจสอบว่าเป็นเท็จหรือไม่ไม่เช่นนั้นจะต้องเป็น json

if(ret == false || ret == "false") {
    // json
}

2

ฉันรู้ว่าหัวข้อนี้ได้รับคำตอบแล้ว แต่การมาที่นี่ไม่ได้ช่วยแก้ปัญหาของฉันได้จริงๆฉันพบฟังก์ชันนี้ที่อื่น บางทีใครบางคนที่มาที่นี่จะพบว่ามันเป็นประโยชน์สำหรับพวกเขา

function getClass(obj) {
  if (typeof obj === "undefined")
    return "undefined";
  if (obj === null)
    return "null";
  return Object.prototype.toString.call(obj)
    .match(/^\[object\s(.*)\]$/)[1];
}


0

หากคุณต้องการที่จะทดสอบอย่างชัดเจนสำหรับ JSON ที่ถูกต้อง (เมื่อเทียบกับกรณีที่ไม่มีค่าที่ส่งกลับที่false) แล้วคุณสามารถใช้วิธีการแยกวิเคราะห์ตามที่อธิบายไว้ที่นี่


0

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

import * as isNull from 'lodash/isNull'
import * as isPlainObject from 'lodash/isPlainObject'
import * as isNumber from 'lodash/isNumber'
import * as isBoolean from 'lodash/isBoolean'
import * as isString from 'lodash/isString'
import * as isArray from 'lodash/isArray'

function isJSON(val) {
  if (isNull(val)
   || isBoolean(val)
   || isString(val))
    return true;
  if (isNumber(val)) 
     return !isNaN(val) && isFinite(val)
  if (isArray(val))
    return Array.prototype.every.call(val, isJSON)
  if (isPlainObject(val)) {
    for (const key of Object.keys(val)) {
      if (!isJSON(val[key]))
        return false
    }
    return true
  }
  return false
}

ฉันเอาแม้กระทั่งเวลาที่จะนำมันขึ้นมาใน NPM เป็นแพคเกจ: https://npmjs.com/package/is-json-object ใช้ร่วมกับสิ่งต่างๆเช่นWebpackเพื่อรับในเบราว์เซอร์

หวังว่านี่จะช่วยใครสักคน!


0

ฉันใช้สิ่งนี้เพื่อตรวจสอบความถูกต้องของวัตถุ JSON

function isJsonObject(obj) {
    try {
        JSON.parse(JSON.stringify(obj));
    } catch (e) {
        return false;
    }
    return true;
}

ฉันใช้สิ่งนี้เพื่อตรวจสอบความถูกต้องของ JSON String

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

0

ฉันลองใช้คำตอบที่แนะนำทั้งหมดแล้วไม่มีอะไรได้ผลสำหรับฉันดังนั้นฉันจึงต้องใช้

jQuery.isEmptyObject()

จอบที่ช่วยคนอื่นในเรื่องนี้


-1

คุณควรส่งคืน json เสมอแต่เปลี่ยนสถานะหรือในตัวอย่างต่อไปนี้คุณสมบัติResponseCode :

if(callbackResults.ResponseCode!="200"){
    /* Some error, you can add a message too */
} else {
    /* All fine, proceed with code */
};

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