문자열이 JSON인지 테스트하는 방법?


191

간단한 AJAX 호출이 있으며 서버는 유용한 데이터가 포함 된 JSON 문자열 또는 PHP 함수에서 생성 된 오류 메시지 문자열을 반환합니다 mysql_error(). 이 데이터가 JSON 문자열인지 또는 오류 메시지인지 테스트하려면 어떻게해야합니까?

isJSON함수 instanceof를 사용하여 무언가가 Array인지 테스트 하는 것처럼 호출되는 함수를 사용하는 것이 좋습니다 .

이것이 내가 원하는거야:

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

아마 eval()그것이 반환되면 사용 하면 undefinedJSON이 아닙니다
MatuDuke

4
이것은 여기서 해결되었습니다 : stackoverflow.com/questions/3710204/…
Reinard

2
고마워요, 죄송합니다. 전에 다른 게시물을 찾지 못했습니다.
jeffery_the_wind

1
기술적으로 이것은 3710204의 속임수가 아닙니다. 왜냐하면 유효한 json인지 여부가 묻기 때문에 json보다 훨씬 높습니다.
carlin.scott

가능한 AJAX
Mehdi Dehghani

답변:


324

JSON.parse 사용

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

53
예외 처리를 사용하여 예상 한 작업을 수행해서는 안됩니다.
luisZavaleta

46
JSON.parse(1234)OR JSON.parse(0)OR JSON.parse(false)OR JSON.parse(null)모두 예외를 발생시키지 않으며 true !!를 반환합니다. 이 답변을 사용하지 마십시오
Zalaboza

19
@Zalaboza 1234, 0, false, 및 null모든 유효한 JSON 값이다. JSON이 객체를 나타내는 지 테스트하는 술어를 원하면 조금 더 수행해야합니다.
Michael Lang

20
JSON.parse문자열을 구문 분석하기 위해 많은 계산을 수행하고 성공하면 json 객체를 제공하지만 일부 사용자가 사용하려는 결과를 버리고 있습니다. 그것은 좋지 않은 것 같습니다. 대신 return {value: JSON.parse(str), valid: true};catch 블록에 return {value: str, valid: false};있습니다. 함수 이름을로 변경했습니다 tryParse().
Nawaz

7
@luisZavaleta 그렇다면 당신은 방법으로 무엇을 제안합니까
PirateApp

80

이 코드는 JSON.parse(1234)또는 JSON.parse(0)또는 JSON.parse(false)또는 JSON.parse(null)모두가 true를 돌려줍니다.

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

그래서 나는 이런 식으로 코드를 다시 작성했습니다.

function isJson(item) {
    item = typeof item !== "string"
        ? JSON.stringify(item)
        : item;

    try {
        item = JSON.parse(item);
    } catch (e) {
        return false;
    }

    if (typeof item === "object" && item !== null) {
        return true;
    }

    return false;
}

테스트 결과 :

isJson 테스트 결과


4
잘 하셨어요! 마지막 if 문은 다음과 같은 간단한 return 문으로 단순화 할 수 있습니다.return (typeof suspect === "object" && suspect !== null);
Nebulosar

39

이것을 다시 한 번 살펴 보겠습니다 (2019+ 이상).

인수 : 값은 같은 true, false, nullJSON 유효 (?)

사실 :이 프리미티브 값은 JSON 구문 분석이 가능 하지만 올바르게 구성된 JSON 구조 는 아닙니다 . JSON 사양 은 JSON이 이름 / 값 쌍 (오브젝트) 또는 정렬 된 값 목록 (배열)의 두 가지 구조로 구축되었음을 나타냅니다.

인수 : 예외 처리를 사용하여 예상되는 작업을 수행해서는 안됩니다.
(이것은 25 개 이상의 공감을 가진 의견입니다!)

사실 : 아니요! 특히 이와 같은 경우 try / catch를 사용하는 것이 합법적입니다. 그렇지 않으면 토큰 화 / 정규식 작업과 같은 많은 문자열 분석 작업을 수행해야합니다. 끔찍한 성능을 발휘합니다.

hasJsonStructure()

일부 데이터 / 텍스트에 올바른 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;
    }
}

용법:

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

safeJsonParse()

또한 일부 데이터를 JavaScript 값으로 구문 분석 할 때주의해야 할 경우에 유용합니다.

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

용법:

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

1
다음과 같이 JSON 사양에 연결합니다. "JSON 텍스트는 JSON 값 문법을 따르는 유니 코드 코드 포인트로 구성된 일련의 토큰입니다." "JSON 값은 객체, 배열, 숫자, 문자열, true, false 또는 null 일 수 있습니다." -JSON은 루트 수준에서만 객체 또는 배열이 될 수 있다는 결론에 어떻게 도달 했습니까? 사양에서이 내용을 볼 수 없으며 "잘 구성된 JSON 구조"에 관한 내용
Relequestual

"JSON은 두 개의 구조에 구축됩니다 ..."로 시작하는 두 번째 단락을 읽습니다. @ json.org 또는 ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf의
Onur Yıldırım

json.org는 정보 제공 용입니다. 연결 한 사양을 읽는 것이 제안을 지원하지 않습니다. 이 사양에는 RFC 8259가 최신 RFC로 언급되어 있습니다. 값이 포함 된 유효한 JSON tex의 예를 살펴보십시오. tools.ietf.org/html/rfc8259#section-13-RFC 8259는 이와 같이 가능한 모호성과 혼동을 해결하도록 설계되었습니다.
Relequestual

답을 다시 읽으십시오. 필자는 프리미티브와 같은 값 (예 : RFC 예제의 텍스트 값)이 JSON "구조"가 아니라고 말합니다. 모호성이 없습니다. JSON으로 구문 분석 할 수 있습니다. JSON으로 구문 분석하는 것이 유효합니다. 그러나 이들은 구조화 된 데이터가 아닙니다. JSON은 주로 객체 또는 배열 일 수있는 구조화 된 데이터에 사용되는 교환 형식»으로 개발되었습니다.
Onur Yıldırım

1
좋아, 우리는 동의한다. 기본은 사양에 따라 유효한 JSON이지만 "구조"는 아닙니다. 괜찮아. 그러나 "인수 : true, false, null과 같은 값은 유효한 JSON (?)입니다. 사실 : 예 및 아니요!" -사양에 따라 유효한 JSON입니다. 그들이 유용한 지 아닌지에 대한 의견은 그 사실과 관련이 없습니다.
Relequestual

20

서버가 JSON으로 응답하는 경우 application/json컨텐츠 유형이 있고 일반 텍스트 메시지로 응답하는 경우 컨텐츠 유형이 있어야 text/plain합니다. 서버가 올바른 컨텐츠 유형으로 응답하는지 확인하고 테스트하십시오.


4
이것은 잘못된 것입니다. 다른 많은 json 호환 미디어 유형이 있습니다. 또한 overrideMimeType컨텐츠 유형 헤더를 대체 할 수 있습니다.
Knu

14

jQuery $.ajax()응답을 사용할 때 responseJSON응답이 JSON 인 경우 속성 을 가지므로 다음과 같이 확인할 수 있습니다.

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

3
이것은 아마도 대부분의 사람들이 찾고있는 대답 일 것입니다. 아마 OP조차도 요.
Kirby

1
이 훨씬 더 우아한 시도의 catch 블록을 사용하는 것보다
아 누락 신하

6

나는 가장 좋은 대답을 좋아하지만 빈 문자열이면 true를 반환합니다. 그래서 여기 수정이 있습니다 :

function isJSON(MyTestStr){
    try {
        var MyJSON = JSON.stringify(MyTestStr);
        var json = JSON.parse(MyJSON);
        if(typeof(MyTestStr) == 'string')
            if(MyTestStr.length == 0)
                return false;
    }
    catch(e){
        return false;
    }
    return true;
}

var json이 사용되지 않습니까? 또는 오류를 잡기 위해?
stackdave

5
var parsedData;

try {
    parsedData = JSON.parse(data)
} catch (e) {
    // is not a valid JSON string
}

그러나 귀하의 http 통화 / 서비스는 항상 동일한 형식의 데이터를 반환해야한다고 제안합니다. 따라서 오류가있는 경우이 오류를 래핑하는 JSON 객체가 있어야합니다.

{"error" : { "code" : 123, "message" : "Foo not supported" } } 

HTTP 상태뿐만 아니라 5xx 코드도 사용할 수 있습니다.


5

글쎄 ... 데이터 수신 방법에 따라 다릅니다. 서버가 JSON 형식 문자열로 응답한다고 생각합니다 (예 : PHP에서 json_encode () 사용). JQuery 게시를 사용하고 응답 데이터를 JSON 형식으로 설정하고 형식이 잘못된 JSON 인 경우 오류가 발생합니다.

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        //Supposing x is a JSON property...
        alert(response.x);

  },
  dataType: 'json',
  //Invalid JSON
  error: function (){ alert("error!"); }
});

그러나 유형 응답을 텍스트로 사용하는 경우 $ .parseJSON을 사용해야합니다. jquery 사이트에 따르면 : "잘못된 JSON 문자열을 전달하면 예외가 발생할 수 있습니다." 따라서 코드는 다음과 같습니다.

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        try {
            parsedData = JSON.parse(response);
        } catch (e) {
            // is not a valid JSON string
        }

  },
  dataType: 'text',
});

물론 위의 예에서 오류 함수의 오류 텍스트를 구문 분석하려고 시도하고 그것이 JSON인지 확실하지 않은 경우가 아니라면 ...
Kirby

큰 대답 response은 비어 있지만 다음으로 이동합니다 success. '(
Henrik Petterson

4

이 아마도 당신이 JSON은 항상에 둘러싸여 것입니다 반환 것을 알고있는 경우 예를 들어, 당신이 할 수있는 테스트 {}다음 해당 문자 또는 다른 해키 방법을 테스트 할 수있다. 또는 json.org JS 라이브러리를 사용하여 구문 분석하고 성공했는지 테스트 할 수 있습니다.

그러나 나는 다른 접근법을 제안 할 것입니다. 호출이 성공하면 PHP 스크립트는 현재 JSON을 반환하지만 그렇지 않으면 다른 것을 반환합니다. 왜 항상 JSON을 반환 하지 않습니까?

예 :

성공적인 전화 :

{ "status": "success", "data": [ <your data here> ] }

잘못된 전화 :

{ "status": "error", "error": "Database not found" }

이렇게하면 클라이언트 쪽 JS를 훨씬 쉽게 작성할 수 있습니다. "상태"멤버와 그에 따른 동작을 확인하기 만하면됩니다.


4

나는 그것을 수행하기 위해 단 2 줄을 사용합니다 :

var isValidJSON = true;
try { JSON.parse(jsonString) } catch { isValidJSON = false }

그게 다야!

그러나 2 개의 트랩이 있음을 명심
하십시오 . 1. JSON.parse(null)리턴 null
2. 임의의 숫자 또는 문자열을 JSON.parse()메소드 로 구문 분석 할 수 있습니다 .
   JSON.parse("5")반품 5
   JSON.parse(5)반품5

코드를 약간 살펴 보자.

// TEST 1
var data = '{ "a": 1 }'

// Avoiding 'null' trap! Null is confirmed as JSON.
var isValidJSON = data ? true : false
try { JSON.parse(data) } catch(e) { isValidJSON = false }

console.log("data isValidJSON: ", isValidJSON);
console.log("data isJSONArray: ", isValidJSON && JSON.parse(data).length ? true : false);

Console outputs:
data isValidJSON:  true
data isJSONArray:  false


// TEST 2
var data2 = '[{ "b": 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data2) } catch(e) { isValidJSON = false }

console.log("data2 isValidJSON: ", isValidJSON);
console.log("data2 isJSONArray: ", isValidJSON && JSON.parse(data2).length ? true : false);

Console outputs:
data2 isValidJSON:  true
data2 isJSONArray:  true


// TEST 3
var data3 = '[{ 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data3) } catch(e) { isValidJSON = false }

console.log("data3 isValidJSON: ", isValidJSON);
console.log("data3 isJSONArray: ", isValidJSON && JSON.parse(data3).length ? true : false);

Console outputs:
data3 isValidJSON:  false
data3 isJSONArray:  false


// TEST 4
var data4 = '2'

var isValidJSON = data ? true : false
try { JSON.parse(data4) } catch(e) { isValidJSON = false }

console.log("data4 isValidJSON: ", isValidJSON);
console.log("data4 isJSONArray: ", isValidJSON && JSON.parse(data4).length ? true : false);


Console outputs:
data4 isValidJSON:  true
data4 isJSONArray:  false


// TEST 5
var data5 = ''

var isValidJSON = data ? true : false
try { JSON.parse(data5) } catch(e) { isValidJSON = false }

console.log("data5 isValidJSON: ", isValidJSON);
console.log("data5 isJSONArray: ", isValidJSON && JSON.parse(data5).length ? true : false);


Console outputs:
data5 isValidJSON:  false
data5 isJSONArray:  false

// TEST 6
var data6; // undefined

var isValidJSON = data ? true : false
try { JSON.parse(data6) } catch(e) { isValidJSON = false }

console.log("data6 isValidJSON: ", isValidJSON);
console.log("data6 isJSONArray: ", isValidJSON && JSON.parse(data6).length ? true : false);

Console outputs:
data6 isValidJSON:  false
data6 isJSONArray:  false

jsfiddle.net/fatmonk/gpn4eyav 에서이 답변에 대한 바이올린을 만들었 으며 여기에는 자체 사용자 테스트 데이터를 추가하는 옵션이 포함되어 있습니다. 이것은 나에게 좋은 라이브러리 함수의 기초처럼 보이지만 Test 1이 유효한 JSON 배열이 아닌 이유에 대해 더 알고 싶습니다.
팻 몽크

[and 를 사용하여 배열을 지정해야하기 때문 ]입니다. 예를 들어 [1, 2, 3]숫자 배열입니다. ["a", "b", "c"]문자열 배열입니다. 그리고 [{"a":1}, {"b":2}]JSON 배열입니다. 귀하의 jsfiddle 작업이 정말 유용합니다!
efkan

저것과 같이 쉬운?! 따라서 테스트 1은 JSON 객체이고 테스트 2는 단일 JSON 객체 요소로 구성된 JSON 배열입니다. 내가 올바르게 이해 했습니까?
Fat Monk

이 중복 가능성이있는 질문 ( stackoverflow.com/questions/3710204/… )은 try / catch를 사용하지 않고이를 달성하는 것에 대해 묻기 때문에 바이올린을 그 목표를 달성하려고 시도했습니다. 포크는 jsfiddle.net/fatmonk/827jsuvr에 있으며 테스트 3을 제외한 위의 모든 테스트에서 작동합니다 JSON.parse. 누구나 try를 사용하지 않고 해당 오류를 피하는 방법을 조언 할 수 있습니까?
Fat Monk

귀하의 jsfiddle응용 프로그램이 유효한 JSON 표현이 없기 때문에 테스트 3의 오류가 발생합니다. 따라서 try-catch위의 테스트 3과 같이 구문 분석 할 때 표현식이 JSON이 아니므로 해당 오류를 포착하고 오류를 평가하는 데 사용해야합니다.try { JSON.parse(data3) } catch(e) { isValidJSON = false }
efkan

2

그것을 해독하고 예외를 잡을 수 있습니다 (native 또는 json2.js ).

try {
  newObj = JSON.parse(myJsonString);
} catch (e) {
  console.log('Not JSON');
}

그러나 응답을 항상 유효한 JSON으로 만드는 것이 좋습니다. MySQL 쿼리에서 오류가 발생하면 다음 오류와 함께 JSON을 다시 보내십시오.

{"error":"The MySQL error string."}

그리고:

if (myParsedJSON.error) {
  console.log('An error occurred: ' + myParsedJSON.error);
}

2

경고 : 에 의존하는 방법에 대해서는 JSON.parse- 둘러싸인 문자열을 배열하고 인용하는 것은 너무 통과 할 것이다. (예 console.log(JSON.parse('[3]'), JSON.parse('"\uD800"')))

객체가 아닌 JSON 프리미티브 (부울, 널, 배열, 숫자, 문자열)를 피하려면 다음을 사용하는 것이 좋습니다.

/* Validate a possible object ie. o = { "a": 2 } */
const isJSONObject = (o) => 
  !!o && (typeof o === 'object') && !Array.isArray(o) && 
  (() => { try { return Boolean(JSON.stringify(o)); } catch { return false } })()

/* Validate a possible JSON object represented as string ie. s = '{ "a": 3 }' */
function isJSONObjectString(s) {
    try {
        const o = JSON.parse(s);
        return !!o && (typeof o === 'object') && !Array.isArray(o)
    } catch {
        return false
    }
}

코드 설명

  • !! o- 허위 아님 (null 제외, typeof 'object'로 등록)
  • (typeof o === 'object') -부울, 숫자 및 문자열 제외
  • ! Array.isArray (o)-배열 제외 (typeof 'object'로 등록)
  • try ... JSON.stringify / JSON.parse- 유효한 JSON인지 확인하도록 JavaScript 엔진에 요청합니다.

hasJsonStructure () 답변을 사용하지 않는 이유는 무엇입니까?

의지하는 toString()것은 좋은 생각이 아닙니다. 다른 JavaScript 엔진이 다른 문자열 표현을 반환 할 수 있기 때문입니다. 일반적으로, 이에 의존하는 메소드는 다른 환경에서 실패하거나 엔진이 문자열 결과를 변경하면 나중에 실패 할 수 있습니다.

왜 예외를 잡는 것이 해킹이 아닌가?

무언가의 타당성을 결정하기 위해 예외를 잡는 것이 올바른 길은 아니라는 것이 밝혀졌습니다. 이것은 일반적으로 좋은 조언이지만 항상 그런 것은 아닙니다. 이 경우 예외 포착은 JavaScript 엔진의 JSON 데이터 유효성 검사 구현에 의존하기 때문에 최상의 경로 일 수 있습니다.

JS 엔진에 의존하면 다음과 같은 장점이 있습니다.

  1. JSON 사양이 변경됨에 따라보다 철저하고 지속적으로 최신 정보 제공
  2. 더 낮은 수준의 코드이므로 더 빠르게 실행될 가능성

JavaScript 엔진에 의지 할 수있는 기회가 주어지면 제안하는 것이 좋습니다. 이 경우 특히 그렇습니다. 이 수 있지만 기분이 예외를 잡기 위해 해키, 당신은 정말 그냥 외부 방법에서 두 가지 반환 상태를 처리하고 있습니다.


1

다음은 Bourne의 답변에서 약간의 수정이있는 코드입니다. JSON.parse (number)는 예외없이 정상적으로 작동하므로 isNaN이 추가되었습니다.

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

0

모든 json 문자열은 '{'또는 '['로 시작하고 해당 '}'또는 ']'로 끝나므로 확인하십시오.

Angular.js가 수행하는 방법은 다음과 같습니다.

var JSON_START = /^\[|^\{(?!\{)/;
var JSON_ENDS = {
  '[': /]$/,
  '{': /}$/
};

function isJsonLike(str) {
    var jsonStart = str.match(JSON_START);
    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
}

https://github.com/angular/angular.js/blob/v1.6.x/src/ng/http.js


@DukeDougal 신경 써야 할까? 때때로 사람들은 '['로 json을 시작하지만 그다지 흔하지는 않습니다.
carlin.scott 2016 년

1
유효한 JSON으로 작동하려면 구문 분석해야합니다. 유효하지 않은 JSON 인 경우 JSON이 아닙니다. 문제는 "문자열이 JSON인지 아닌지 어떻게 알 수 있습니까?"입니다. 귀하의 접근 방식에 따르면 이것은 JSON {fibble입니다. 실제로는 JSON이 아닙니다. 자체적으로 숫자 1과 같은 경우를 고려하십시오-유효한 JSON입니다.
Duke Dougal

1
"유효하지 않은 JSON이면 JSON이 아닙니다". "유효한"이라는 단어를 사용해야한다는 사실은 단순히 json 이상의 의미에 자격을 추가하고 있음을 나타냅니다. 문제는 단순히 "이것은 json"이고 내 코드 예제는 추가 요구 사항을 가정하지 않고 그 질문에 완벽하게 대답합니다.
carlin.scott 2016 년

일부 템플릿 시스템을 사용하고 있고 { someValue }자동으로 유효성 검사를 통과하는 것과 같은 것이 있다면 나쁜 생각 입니다.
ncubica

@ ncubica 그래서 json 이외의 템플릿을 사용하고 문자열에는 중괄호를 사용하는 자리 표시 자 만 포함되며 템플릿 엔진은 자리 표시자를 실제 값으로 바꾸지 못합니까? 또한 Duke에게 이미 설명했듯이 원래 질문에는 유효성 검사가 언급되어 있지 않습니다. 그들은 그것이 json처럼 보이는지 아닌지 알고 싶었습니다.
carlin.scott

0

Typescript 모드 에서 제안 합니다.

export function stringify(data: any): string {
    try {
         return JSON.stringify(data)
    } catch (e) {
         return 'NOT_STRINGIFIABLE!'
    }
}

0

나는 이것을 사용했다 (다른 답변의 혼합, 그러나 어쨌든) :

const isJSON = str => {
  if (typeof str === 'string'){
    try {
      JSON.parse(str)
      return true
    } catch(e){
    }
  }
  return false
}



[null, undefined, false, true, [], {}, 
 '', 'asdf', '{}', '[]', "{\"abc\": 2}","{\"abc\": \"2\"}"]
  .map(el => {
      console.log(`[>${el}<] - ${isJSON(el)}`)
})

console.log('-----------------')


0

숫자, null, 문자열의 유효성을 검사하기 때문에 다음 중 하나를 시도 할 수 있지만 위에 표시된 답변이 올바르게 작동하지 않으므로 위 함수의 수정 일뿐입니다.

function isJson(str) {
  try {
      const obj = JSON.parse(str);
      if (obj && typeof obj === `object`) {
        return true;
      }
    } catch (err) {
      return false;
    }
   return false;
}

-1

이전 답변 외에도 "{}"와 같은 JSON 형식의 유효성을 검사해야하는 경우 다음 코드를 사용할 수 있습니다.

const validateJSON = (str) => {
  try {
    const json = JSON.parse(str);
    if (Object.prototype.toString.call(json).slice(8,-1) !== 'Object') {
      return false;
    }
  } catch (e) {
    return false;
  }
  return true;
}

사용 예 :

validateJSON('{}')
true
validateJSON('[]')
false
validateJSON('')
false
validateJSON('2134')
false
validateJSON('{ "Id": 1, "Name": "Coke" }')
true
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.