JSON.parse가 허용하지 않는 문자
아래의 웹 페이지를 브라우저로 보면,
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script>
function parse_input() {
var txt = '{"firstname":"My\tName"}';
var obj = JSON.parse(txt);
}
</script>
</head>
<body>
<input type="button" onclick="parse_input()" value="test" />
</body>
</html>
F12 개발자 콘솔을 통해 parse_input 함수 수행 시 다음과 같은 오류가 나는 것을 볼 수 있습니다.
[Internet Explorer 11]
SCRIPT1014: Invalid character
encode_sample.html (15,13)
[Edge]
SCRIPT5655: SCRIPT5655: JSON.parse Error: Invalid character at position:17
[Chrome]
VM32:1 Uncaught SyntaxError: Unexpected token in JSON at position 18
at JSON.parse (<anonymous>)
at parse_input (encode_sample.html:15)
at HTMLInputElement.onclick (encode_sample.html:22)
원인은 json 텍스트에 포함된 탭(\t) 문자 때문입니다. 따라서 이런 문제를 예방하려면 해당 텍스트들의 입력 시에 미리 json parse로 테스트하든가, 아니면 다음과 같은 식으로 문자열 필터링을 하는 것이 좋습니다.
function check_validInput(txt) {
var replacedText = txt.replace(/[\u0000-\u0019]+/g, " "); // https://stackoverflow.com/questions/14432165/uncaught-syntaxerror-unexpected-token-with-json-parse/41498991
if (txt != replacedText) {
alert("INVALID");
return false;
}
alert("VALID");
return true;
}
재미있는 것은, 이러한 탭 문자 등의 것들이 본래 JSON 표준의 제약은 아니라는 점입니다. 일례로, C#의 JSON.NET으로 실행하면 잘 파싱이 됩니다.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string txt = "{ \"firstname\": \"test\t\tqwer\" }";
object result = Newtonsoft.Json.JsonConvert.DeserializeObject(txt);
Console.WriteLine(result);
}
}
}
/*
출력 결과:
{
"firstname": "test\t\tqwer"
}
*/
그런데 3개의 브라우저(IE, Edge, Chrome) 모두 마치 서로 같은 JSON parser 코드를 공유하기라도 한 것처럼 오류가 발생한다는 것이 매우 흥미롭습니다. 사실, JSON 포맷 표준에서는,
JSON 데이터 교환 포맷
; https://techhtml.github.io/ECMA-404/
ECMA-404
; http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
문자열의 범위로,
String: a sequence of zero or more Unicode characters. Strings are delimited with double-quotation marks and support a backslash escaping syntax.
분명히 '\'를 이용한 이스케이프 문자를 지원한다고 명시합니다. 또한, 다음의 표준 문서를 봐도,
Standard ECMA-262
5.1 Edition / June 2011
ECMAScript® Language Specification
; https://www.ecma-international.org/ecma-262/5.1/#sec-15.12.2
JSON 구문의 가능한 값으로 "JSONString"이라고 명시하고 있으며 또한 stringify의 "NOTE 3"에 다음과 같은 문구가 나옵니다.
String values are wrapped in double quotes. The characters " and \ are escaped with \ prefixes. Control characters are replaced with escape sequences \uHHHH, or with the shorter forms, \b (backspace), \f (formfeed), \n (newline), \r (carriage return), \t (tab).
혹시 왜? 브라우저의 JSON.parse 메서드가 \b, \f, \n, \r, \t 문자들에 대해 파싱 오류가 발생하는지 정확한 이력을 아시는 분은 덧글 부탁드립니다. ^^
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]