javascript - Cum să testezi dacă un șir de caractere este JSON sau nu?


Am un apel AJAX simplu, iar serverul va returna fie un șir JSON cu date utile, fie un șir de mesaj de eroare produs de funcția PHP mysql_error(). Cum pot testa dacă aceste date sunt un șir JSON sau mesajul de eroare.

Ar fi frumos să folosești o funcție numită isJSON exact așa cum poți folosi funcția instanceof pentru a testa dacă ceva este un Array.

Asta este ceea ce vreau:

if (isJSON(data)){
    //do some data stuff
}else{
    //report the error
    alert(data);
}

Răspuns #1

Folosește JSON.parse

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

Răspunsul #2

Folosirea JSON.parse() are câteva dezavantaje:

  1. JSON.parse(1234) sau
  2. JSON.parse(0) sau
  3. JSON.parse(false) sau
  4. JSON.parse(null)

toate vor returna adevărat.

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

function testIsJson(value, expected) {
  console.log(`Expected: ${expected}, Actual: ${isJson(value)}`); 
}

// All of the following codes are expected to return false.
// But actually returns true.
testIsJson(1234, false);
testIsJson(0, false);
testIsJson(false, false);
testIsJson(null, false);

Cod care gestionează alarmele false

Așa că am rescris codul în acest mod:

function isJson(item) {
  let value = typeof item !== "string" ? JSON.stringify(item) : item;    
  try {
    value = JSON.parse(value);
  } catch (e) {
    return false;
  }
    
  return typeof value === "object" && value !== null;
}

Rezultatul testului:

function isJson(item) {
  let value = typeof item !== "string" ? JSON.stringify(item) : item;
  try {
    value = JSON.parse(value);
  } catch (e) {
    return false;
  }

  return typeof value === "object" && value !== null;
}

function testIsJson(value, expected) {
  console.log(`Expected: ${expected}, Actual: ${isJson(value)}`);
}

const validJson = { "foo": "bar" };
const notValidJson = '{ "foo": "bar" } invalid';

// expected: true
testIsJson(validJson, true);

// expected: false
testIsJson(1234, false);
testIsJson(0, false);
testIsJson(notValidJson, false);
testIsJson(false, false);
testIsJson(null, false);

Răspunsul #3

Hai să recapitulăm asta (pentru 2019+).

Argument: Valorile precum true, false, null sunt JSON valide (?)

FAPT: Aceste valori primitive sunt parsabile în JSON, dar nu sunt structuri JSON bine formate. Specificația JSON indică faptul că JSON este construit pe două structuri: O colecție de perechi nume/valoare (obiect) sau o listă ordonată de valori (array).

Argument: Gestionarea excepțiilor nu ar trebui folosită pentru a face ceva așteptat.
(Acesta este un comentariu care are peste 25 de voturi pozitive!)

FACT: Nu! Este cu siguranță legal să folosești try/catch, mai ales într-un caz ca acesta. Altfel, ar trebui să faci o mulțime de analize de șiruri de caractere, cum ar fi tokenizare sau operații regex; ceea ce ar avea o performanță foarte slabă.

areStructuraJson()

Acest lucru este util dacă scopul tău este să verifici dacă unele date/text au un format corect de schimb JSON.

function hasJsonStructure(str) {
    if (typeof str !== 'string') return false;
    try {
        const result = JSON.parse(str);
        const type = Object.prototype.toString.call(result);
        return type === '[object Object]' 
            || type === '[object Array]';
    } catch (err) {
        return false;
    }
}

Utilizare :

hasJsonStructure('true')             // —» false
hasJsonStructure('{"x":true}')       // —» true
hasJsonStructure('[1, false, null]') // —» true

safeJsonParse()

Și acest lucru este util dacă vrei să fii atent atunci când analizezi unele date pentru a le transforma într-o valoare JavaScript.

function safeJsonParse(str) {
    try {
        return [null, JSON.parse(str)];
    } catch (err) {
        return [err];
    }
}

Utilizare :

const [err, result] = safeJsonParse('[Invalid JSON}');
if (err) {
    console.log('Failed to parse JSON: ' + err.message);
} else {
    console.log(result);
}

Răspunsul #4

Dacă serverul răspunde cu JSON, atunci ar trebui să aibă un tip de conținut application/json, iar dacă răspunde cu un mesaj text simplu, atunci ar trebui să aibă un tip de conținut text/plain. Asigurați-vă că serverul răspunde cu tipul de conținut corect și testați acest lucru.

Răspunsul #5

Când folosești jQuery $.ajax(), răspunsul va avea proprietatea responseJSON dacă răspunsul a fost JSON, acest lucru poate fi testat astfel:

if (xhr.hasOwnProperty('responseJSON')) {}