JavaScript 및 .NET의 JSON(JavaScript Object Notation) 소개
JavaScript 및 .NET의 JSON(JavaScript Object Notation) 소개
아티프 아지즈, 스콧 미첼
2007년 2월
적용 대상:
JSON
Ajax
요약: 이 문서에서는 Ajax 스타일 웹 애플리케이션에 더 적합한 표준화된 데이터 교환 형식을 제공하는 개방형 및 텍스트 기반 데이터 교환 형식인 JavaScript 개체 표기법(또는 JSON)에 대해 설명합니다. (인쇄된 22페이지)
콘텐츠
소개
JavaScript의 리터럴 표기법 이해
JSON과 XML 비교
JavaScript를 사용하여 JSON 메시지 만들기 및 구문 분석
.NET Framework JSON 작업
결론
참조
소개
원격 컴퓨터와 통신할 애플리케이션을 디자인할 때 데이터 형식 및 교환 프로토콜을 선택해야 합니다. 다양한 개방형 표준화된 옵션이 있으며 이상적인 선택은 애플리케이션 요구 사항 및 기존 기능에 따라 달라집니다. 예를 들어 SOAP 기반 웹 서비스는 SOAP 봉투 내에 래핑된 XML 페이로드의 데이터 형식을 지정합니다.
XML은 많은 애플리케이션 시나리오에서 잘 작동하지만 일부 단점이 있어 다른 시나리오에서는 적합하지 않습니다. XML이 이상적이지 않은 공간 중 하나는 Ajax 스타일의 웹 애플리케이션을 사용하는 것입니다. Ajax는 전체 페이지 포스트백 대신 웹 서버에 대한 대역 외 경량 호출을 사용하여 더 뛰어난 사용자 환경을 제공하는 대화형 웹 애플리케이션을 빌드하는 데 사용되는 기술입니다. 이러한 비동기 호출은 JavaScript를 사용하여 클라이언트에서 시작되며 데이터 서식 지정, 웹 서버로 전송, 반환된 데이터 구문 분석 및 작업이 포함됩니다. 대부분의 브라우저는 XML을 생성, 전송 및 구문 분석할 수 있지만 JavaScript 개체 표기법(또는 JSON)은 Ajax 스타일 웹 애플리케이션에 더 적합한 표준화된 데이터 교환 형식을 제공합니다.
JSON은 개방형 텍스트 기반 데이터 교환 형식입니다( RFC 4627 참조). XML과 마찬가지로 사람이 읽을 수 있고 플랫폼에 독립적이며 구현의 광범위한 가용성을 누릴 수 있습니다. JSON 표준에 따라 서식이 지정된 데이터는 가볍고 JavaScript 구현에서 매우 쉽게 구문 분석할 수 있으므로 Ajax 웹 애플리케이션에 이상적인 데이터 교환 형식입니다. 주로 데이터 형식이므로 JSON은 Ajax 웹 애플리케이션에만 국한되지 않으며 애플리케이션이 구조화된 정보를 텍스트로 교환하거나 저장해야 하는 거의 모든 시나리오에서 사용할 수 있습니다.
이 문서에서는 JSON 표준, JavaScript와의 관계 및 XML과 비교하는 방법을 살펴봅니다. .NET용 오픈 소스 JSON 구현인 Jayrock에 대해 설명하고 JSON 메시지를 만들고 구문 분석하는 예제는 JavaScript 및 C#에서 제공됩니다.
JavaScript의 리터럴 표기법 이해
리터럴은 프로그래밍 언어에서 4의 상수 정수 값 또는 "Hello, World" 문자열과 같은 고정 값을 문자 그대로 표현하는 데 사용됩니다. 컨트롤 문의 조건 일부, 함수를 호출할 때 입력 매개 변수, 변수 할당 등 식이 허용되는 대부분의 언어에서 리터럴을 사용할 수 있습니다. 예를 들어 다음 C# 및 Visual Basic 코드는 상수 정수 값이 42인 x 변수를 초기화합니다.
int x = 42; // C#
Dim x As Integer = 42 ' Visual Basic
다양한 프로그래밍 언어를 사용하면 다양한 형식의 리터럴을 사용할 수 있습니다. 대부분의 프로그래밍 언어는 정수, 부동 소수점 숫자, 문자열 및 부울과 같은 스칼라 형식에 대해 최소한 리터럴을 지원합니다. JavaScript의 흥미로운 점은 스칼라 형식 외에도 배열 및 개체와 같은 구조화된 형식에 대한 리터럴도 지원한다는 것입니다. 이 기능을 사용하면 배열 및 개체의 주문형 생성 및 초기화를 위한 자세한 구문을 사용할 수 있습니다.
JavaScript의 배열 리터럴은 0개 이상의 식으로 구성되며 각 식은 배열의 요소를 나타냅니다. 배열 요소는 대괄호([])로 묶고 쉼표로 구분됩니다. 다음 예제에서는 7개 대륙의 이름을 포함하는 7개의 문자열 요소가 있는 배열을 문자 그대로 정의합니다.
var continents = ["Europe", "Asia", "Australia", "Antarctica", "North
America", "South America", "Africa"];
alert(continents[0] + " is one of the " + continents.length + "
continents.");
이제 리터럴 표기법 없이 JavaScript에서 배열을 만들고 초기화하는 방법과 비교합니다.
var continents = new Array();
continents[0] = "Europe";
continents[1] = "Asia";
continents[2] = "Australia";
continents[3] = "Antarctica";
continents[4] = "North America";
continents[5] = "South America";
continents[6] = "Africa";
개체 리터럴은 개체의 멤버와 해당 값을 정의합니다. 개체 멤버 및 값 목록은 중괄호({})로 묶고 각 멤버는 쉼표로 구분됩니다. 각 멤버 내에서 이름과 값은 콜론(:)으로 구분됩니다. 다음 예제에서는 개체를 만들고 해당 값이 "123 Anywhere St.", "Springfield", "99999"인 Address, City 및 PostalCode라는 세 멤버로 초기화합니다.
var mailingAddress = {
"Address" : "123 Anywhere St.",
"City" : "Springfield",
"PostalCode" : 99999
};
alert("The package will be shipped to postal code " +
mailingAddress.PostalCode);
지금까지 제시된 예제에서는 배열 및 개체 리터럴 내에서 문자열 및 숫자 리터럴을 사용하는 것을 보여 줍니다. 배열 요소와 개체 멤버 값이 개체 및 배열 리터럴을 사용할 수 있도록 표기법을 재귀적으로 사용하여 전체 그래프를 표현할 수도 있습니다. 예를 들어 다음 코드 조각은 배열이 멤버(PhoneNumbers)로 있는 개체를 보여 줍니다. 여기서 배열은 개체 목록으로 구성됩니다.
var contact = {
"Name": "John Doe",
"PermissionToCall": true,
"PhoneNumbers": [
{
"Location": "Home",
"Number": "555-555-1234"
},
{
"Location": "Work",
"Number": "555-555-9999 Ext. 123"
}
]
};
if (contact.PermissionToCall)
{
alert("Call " + contact.Name + " at " + contact.PhoneNumbers[0].Number);
}
참고 JavaScript에 대한 리터럴 지원에 대한 자세한 내용은 리터럴 섹션의 핵심 JavaScript 1.5 가이드에서 확인할 수 있습니다.
JavaScript 리터럴에서 JSON으로
JSON은 JavaScript에서 리터럴 개체 표기법의 하위 집합에서 만든 데이터 교환 형식입니다. 리터럴 값에 대해 JavaScript에서 허용하는 구문은 매우 유연하지만 JSON에는 훨씬 더 엄격한 규칙이 있다는 점에 유의해야 합니다. 예를 들어 JSON 표준에 따라 개체 멤버의 이름은 유효한 JSON 문자열 이어야 합니다 . JSON의 문자열은 따옴표로 묶 어야 합니다 . 반면 JavaScript에서는 개체 멤버 이름을 따옴표나 아포스트로피로 구분하거나 멤버 이름이 예약된 JavaScript 키워드(keyword) 충돌하지 않는 한 따옴표를 생략할 수 있습니다. 마찬가지로 JSON의 배열 요소 또는 개체 멤버 값은 매우 제한된 집합으로 제한됩니다. 그러나 JavaScript에서 배열 요소 및 개체 멤버 값은 함수 호출 및 정의를 포함하여 거의 모든 유효한 JavaScript 식을 참조할 수 있습니다.
JSON의 매력은 단순함입니다. JSON 표준에 따라 서식이 지정된 메시지는 단일 최상위 개체 또는 배열로 구성됩니다. 배열 요소와 개체 값은 개체, 배열, 문자열, 숫자, 부울 값(true 및 false) 또는 null일 수 있습니다. 즉, 간단히 말해서, JSON 표준입니다! 매우 간단합니다. 표준 에 대한 보다 공식적인 설명은 www.json.org 또는 RFC 4627 을 참조하세요.
JSON의 아픈 점 중 하나는 날짜/시간 리터럴이 없다는 것입니다. 많은 사람들이 JSON을 처음 접할 때 이 사실을 알게 되어 놀랍고 실망합니다. 날짜/시간 리터럴의 부재에 대한 간단한 설명(위안 여부)은 JavaScript에 하나도 없다는 것입니다. JavaScript의 날짜 및 시간 값에 대한 지원은 Date 개체를 통해 전적으로 제공됩니다. 따라서 JSON을 데이터 형식으로 사용하는 대부분의 애플리케이션은 일반적으로 날짜 및 시간 값을 표현하기 위해 문자열 또는 숫자를 사용하는 경향이 있습니다. 문자열을 사용하는 경우 일반적으로 ISO 8601 형식으로 예상할 수 있습니다. 대신 숫자를 사용하는 경우 epoch가 1970년 1월 1일 자정(UTC)으로 정의된 epoch 이후 UTC(Universal Coordinated Time)의 시간(밀리초)을 의미하는 값이 사용됩니다. 다시 말하지만, 이것은 단순한 규칙이며 JSON 표준의 일부가 아닙니다. 데이터를 다른 애플리케이션과 교환하는 경우 JSON 리터럴 내에서 날짜 및 시간 값을 인코딩하는 방법을 보려면 해당 설명서를 검사 합니다. 예를 들어 Microsoft의 ASP.NET AJAX는 설명된 규칙을 모두 사용하지 않습니다. 대신 .NET DateTime 값을 JSON 문자열로 인코딩합니다. 여기서 문자열의 콘텐츠는 \/Date(ticks)\/ 이고 여기서 틱 은 epoch(UTC) 이후 밀리초를 나타냅니다. 따라서 1989년 11월 29일 오전 4:55:30 UTC는 "\/Date(628318530718)\/"로 인코딩됩니다. 인코딩의 다소 모순된 선택에 대한 몇 가지 근거는 "ASP.NET AJAX의 JSON 날짜 및 시간 문자열 내부"를 참조하세요.
JSON과 XML 비교
JSON과 XML을 모두 사용하여 텍스트 기반의 사람이 읽을 수 있는 데이터 교환 형식으로 네이티브 메모리 내 개체를 나타낼 수 있습니다. 또한 두 데이터 교환 형식은 동형입니다. 한 형식의 텍스트를 지정하면 다른 형식에서는 동일한 텍스트가 생각할 수 있습니다. 예를 들어 Yahoo!'의 공개적으로 액세스할 수 있는 웹 서비스 중 하나를 호출할 때 querystring 매개 변수를 통해 응답의 형식을 XML 또는 JSON으로 지정해야 하는지 여부를 나타낼 수 있습니다. 따라서 데이터 교환 형식을 결정할 때 다른 형식을 은색 글머리 기호로 선택하는 것은 단순한 문제가 아니라 특정 애플리케이션에 가장 적합한 특성을 가진 형식입니다. 예를 들어 XML은 문서 텍스트 표시에 뿌리를 두고 있으며 XHTML에서 알 수 있듯이 해당 공간에서 매우 잘 빛나는 경향이 있습니다. 반면 JSON은 프로그래밍 언어 유형 및 구조에 뿌리를 두고 있으므로 구조화된 데이터를 교환하는 보다 자연스럽고 쉽게 사용할 수 있는 매핑을 제공합니다. 다음 표는 이러한 두 시작점 외에도 XML 및 JSON의 주요 특성을 이해하고 비교하는 데 도움이 됩니다.
XML과 JSON 간의 주요 특징 차이점
특성 | XML | JSON |
---|---|---|
데이터 유형 | 데이터 형식의 개념을 제공하지 않습니다. 형식 정보를 추가하려면 XML 스키마 를 사용해야 합니다. | 스칼라 데이터 형식과 배열 및 개체를 통해 구조화된 데이터를 표현하는 기능을 제공합니다. |
배열 지원 | 배열 콘텐츠를 내부 요소로 모델링하는 외부 자리 표시자 요소를 사용하는 경우와 같이 규칙에 따라 배열을 표현해야 합니다. 일반적으로 외부 요소는 내부 요소에 사용되는 이름의 복수 형식을 사용합니다. | 네이티브 배열 지원. |
개체 지원 | 개체는 특성 및 요소의 혼합 사용을 통해 규칙으로 표현되어야 합니다. | 네이티브 개체 지원. |
Null 지원 | XML instance 문서의 요소에 xsi:nil을 사용하고 해당 네임스페이스를 가져와야 합니다. | 기본적으로 null 값을 인식합니다. |
의견 | 기본 지원 및 일반적으로 API를 통해 사용할 수 있습니다. | 지원되지 않습니다. |
네임스페이스 | 네임스페이스를 지원하여 문서를 결합할 때 이름 충돌 위험을 제거합니다. 또한 네임스페이스를 사용하면 기존 XML 기반 표준을 안전하게 확장할 수 있습니다. | 네임스페이스의 개념이 없습니다. 명명 충돌은 일반적으로 개체를 중첩하거나 개체 멤버 이름에 접두사를 사용하여 방지됩니다(전자는 실제로 선호됨). |
서식 결정 | 복잡. 애플리케이션 형식을 XML 요소 및 특성에 매핑하는 방법을 결정하려면 더 많은 노력이 필요합니다. 요소 중심 또는 특성 중심 접근 방식이 더 나은지 여부에 대한 열띤 논쟁을 만들 수 있습니다. | 단순하고 애플리케이션 데이터에 대한 훨씬 더 직접적인 매핑을 제공합니다. 유일한 예외는 날짜/시간 리터럴이 없는 것일 수 있습니다. |
크기 | 특히 서식 지정에 대한 요소 중심 접근 방식을 사용하는 경우 문서 크기가 길어지는 경향이 있습니다. | 구문은 매우 다양하며 표현된 데이터에 의해 대부분의 공간이 사용되는 서식이 지정된 텍스트를 생성합니다. |
JavaScript에서 구문 분석 | 텍스트를 JavaScript 개체에 다시 매핑하려면 XML DOM 구현 및 추가 애플리케이션 코드가 필요합니다. | 텍스트를 구문 분석하는 데 필요한 추가 애플리케이션 코드가 없습니다. 는 JavaScript의 eval 함수를 사용할 수 있습니다. |
학습 곡선 | 일반적으로 XPath, XML 스키마, XSLT, XML 네임스페이스, DOM 등 여러 기술을 함께 사용해야 합니다. | JavaScript 또는 기타 동적 프로그래밍 언어로 배경을 가진 개발자에게 이미 익숙한 매우 간단한 기술 스택입니다. |
JSON은 비교적 새로운 데이터 교환 형식이며 현재 XML에서 제공하는 수년간의 채택 또는 공급업체 지원이 없습니다(JSON이 빠르게 따라잡고 있지만). 다음 표에서는 XML 및 JSON 공간의 현재 업무 상태를 강조 표시합니다.
XML과 JSON 간의 지원 차이점
지원 | XML | JSON |
---|---|---|
도구 | 많은 업계 공급업체에서 널리 사용할 수 있는 완성도 높은 도구 집합을 누리고 있습니다. | 편집기 및 포맷터와 같은 풍부한 도구 지원은 부족합니다. |
Microsoft .NET Framework | .NET Framework 버전 1.0 이후 매우 훌륭하고 성숙한 지원. XML 지원은 BCL(기본 클래스 라이브러리)의 일부로 사용할 수 있습니다. 관리되지 않는 환경의 경우 MSXML이 있습니다. | ASP.NET AJAX의 일부로 초기 구현을 제외하고 지금까지 없음. |
플랫폼 및 언어 | 파서 및 포맷터는 많은 플랫폼 및 언어(상용 및 오픈 소스 구현)에서 널리 사용할 수 있습니다. | 파서 및 포맷터는 이미 여러 플랫폼 및 여러 언어에서 사용할 수 있습니다. 좋은 참조 집합은 json.org 참조하세요. 현재 대부분의 구현은 오픈 소스 프로젝트인 경향이 있습니다. |
통합 언어 | 업계 공급업체는 현재 언어 내에서 말 그대로 지원을 실험하고 있습니다. 자세한 내용은 Microsoft의 LINQ 프로젝트를 참조하세요. | JavaScript/ECMAScript에서만 기본적으로 지원됩니다. |
참고 두 테이블 모두 비교 지점의 포괄적인 목록이 아닙니다. 두 데이터 형식을 비교할 수 있는 각도가 더 있지만 이러한 핵심 요소는 초기 인상을 작성하기에 충분하다고 생각했습니다.
JavaScript를 사용하여 JSON 메시지 만들기 및 구문 분석
JSON을 데이터 교환 형식으로 사용하는 경우 두 가지 일반적인 작업은 네이티브 및 메모리 내 표현을 JSON 텍스트 표현으로 바꾸고 그 반대의 경우도 마찬가지입니다. 안타깝게도 작성 당시 JavaScript는 지정된 개체 또는 배열에서 JSON 텍스트를 만드는 기본 제공 함수를 제공하지 않습니다. 이러한 메서드는 2007년에 ECMAScript 표준의 네 번째 버전에 포함될 것으로 예상됩니다. 이러한 JSON 형식 지정 함수가 공식적으로 JavaScript에 추가되고 널리 사용되는 구현에서 널리 사용할 수 있을 때까지 에서 http://www.json.org/json.js다운로드할 수 있는 참조 구현 스크립트를 사용합니다.
이 작성 당시의 최신 반복에서 www.json.org json.js 스크립트는 배열, 문자열, 부울, 개체 및 기타 JavaScript 형식에 toJSONString() 함수를 추가합니다. 스칼라 형식(예: Number 및 Boolean)에 대한 toJSONString() 함수는 instance 값의 문자열 표현만 반환하면 되므로 매우 간단합니다. 예를 들어 부울 형식에 대한 toJSONString() 함수는 값이 true이면 문자열 "true"를 반환하고, 그렇지 않으면 "false"를 반환합니다. 배열 및 개체 형식에 대한 toJSONString() 함수가 더 흥미롭습니다. Array 인스턴스의 경우 포함된 각 요소 에 대한 toJSONString() 함수가 순서대로 호출되며 결과는 각 결과를 구분하기 위해 쉼표와 연결됩니다. 대괄호로 묶인 최종 출력입니다. 마찬가지로 Object 인스턴스의 경우 각 멤버가 열거되고 toJSONString() 함수가 호출됩니다. 멤버 이름과 해당 값의 JSON 표현은 중간에 콜론과 연결됩니다. 각 멤버 이름과 값 쌍은 쉼표로 구분되고 전체 출력은 중괄호로 묶습니다.
toJSONString() 함수의 순 결과는 모든 형식을 단일 함수 호출을 사용하여 JSON 형식으로 변환할 수 있다는 것입니다. 다음 JavaScript는 Array 개체를 만들고 설명 목적으로 자세한 정보 및 비리터럴 메서드를 사용하여 의도적으로 7개의 String 요소를 추가합니다. 그런 다음, 배열 JSON 표현을 표시합니다.
// josn.js must be included prior to this point
var continents = new Array();
continents.push("Europe");
continents.push("Asia");
continents.push("Australia");
continents.push("Antarctica");
continents.push("North America");
continents.push("South America");
continents.push("Africa");
alert("The JSON representation of the continents array is: " +
continents.toJSONString());
그림 1. toJSONString() 함수는 JSON 표준에 따라 형식이 지정된 배열을 내보냅니다.
JSON 텍스트를 구문 분석하는 것이 더 간단합니다. JSON은 JavaScript 리터럴의 하위 집합일 뿐이므로 원본 JSON 텍스트를 JavaScript 소스 코드로 처리하는 eval(expr) 함수,
를 사용하여 메모리 내 표현으로 구문 분석할 수 있습니다.
eval 함수는 유효한 JavaScript 코드 문자열을 입력으로 수락하고 식을 평가합니다. 따라서 JSON 텍스트를 네이티브 표현으로 변환하는 데 필요한 코드는 다음과 같습니다.
var value = eval( "(" + jsonText + ")" );
참고 추가 괄호는 eval 을 식처럼 소스 입력을 무조건 처리하게 만드는 데 사용됩니다. 이는 개체에 특히 중요합니다. "{}" 문자열(빈 개체 의미)과 같이 개체를 정의하는 JSON 텍스트가 포함된 문자열로 eval을 호출하려고 하면 구문 분석된 결과로 정의되지 않은 값만 반환됩니다. 괄호는 JavaScript 파서가 문 블록을 정의하는 중괄호가 아닌 Object instance 대한 리터럴 표기법으로 최상위 중괄호를 표시하도록 합니다. 또한 최상위 항목이 eval("[1,2,3]")과 같이 배열인 경우에도 동일한 문제가 발생하지 않습니다. 그러나 균일성을 위해 JSON 텍스트는 항상 eval 을 호출하기 전에 괄호로 묶어야 하므로 원본을 해석하는 방법에 대한 모호성이 없습니다.
리터럴 표기법을 평가할 때 리터럴 구문에 해당하는 instance 반환되고 값에 할당됩니다. eval 함수를 사용하여 배열에 대한 리터럴 표기법을 구문 분석하고 결과 배열을 변수 대륙에 할당하는 다음 예제를 생각해 보세요.
var arrayAsJSONText = '["Europe", "Asia", "Australia", "Antarctica",
"North America", "South America", "Africa"]';
var continents = eval( arrayAsJSONText );
alert(continents[0] + " is one of the " + continents.length + "
continents.");
물론 실제로 평가된 JSON 텍스트는 위의 경우와 같이 하드 코딩되지 않고 일부 외부 원본에서 제공됩니다.
eval 함수는 전달된 식이 무엇이든 맹목적으로 평가합니다. 따라서 신뢰할 수 없는 원본에는 잠재적으로 위험한 JavaScript를 JSON 데이터를 구성하는 리터럴 표기법과 함께 포함하거나 혼합할 수 있습니다. 원본을 신뢰할 수 없는 시나리오에서는 parseJSON() 함수( json.js)를 사용하여 JSON 텍스트를 구문 분석하는 것이 좋습니다.
// Requires json.js
var continents = arrayAsJSONText.parseJSON();
parseJSON() 함수도 eval을 사용하지만 arrayAsJSONText에 포함된 문자열이 JSON 텍스트 표준을 준수하는 경우에만 사용됩니다. 이 작업은 영리한 정규식 테스트를 사용하여 수행합니다.
.NET Framework JSON 작업
JSON 텍스트는 매력의 일부인 JavaScript 코드에서 쉽게 만들고 구문 분석할 수 있습니다. 그러나 ASP.NET 웹 애플리케이션에서 JSON을 사용하는 경우 서버 쪽 코드가 Visual Basic 또는 C#으로 작성될 가능성이 높기 때문에 브라우저만 JavaScript 지원을 사용합니다.
ASP.NET 위해 설계된 대부분의 Ajax 라이브러리는 프로그래밍 방식으로 JSON 텍스트를 만들고 구문 분석할 수 있도록 지원합니다. 따라서 .NET 애플리케이션에서 JSON을 사용하려면 이러한 라이브러리 중 하나를 사용하는 것이 좋습니다. 오픈 소스 및 타사 옵션이 많이 있으며 Microsoft에는 ASP.NET AJAX라는 자체 Ajax 라이브러리도 있습니다.
이 문서에서는 공동 저자 Atif Aziz가 만든 Microsoft .NET Framework JSON의 오픈 소스 구현인 Jayrock을 사용하는 예제를 살펴보겠습니다. 세 가지 이유로 AJAX를 ASP.NET 대신 Jayrock을 사용하기로 결정했습니다.
- Jayrock은 오픈 소스이므로 필요에 따라 확장하거나 사용자 지정할 수 있습니다.
- Jayrock은 ASP.NET 1.x, 2.0 및 Mono 애플리케이션에서 사용할 수 있지만 ASP.NET AJAX는 ASP.NET 버전 2.0용입니다.
- Jayrock의 scope JSON 및 JSON-RPC로 제한되며 전자는 이 문서의 기본 초점입니다. ASP.NET AJAX에는 JSON 텍스트 만들기 및 구문 분석에 대한 지원이 포함되어 있지만, 주요 목적은 ASP.NET 엔드 투 엔드 Ajax 스타일의 웹 애플리케이션을 빌드하기 위한 풍부한 플랫폼을 제공하는 것입니다. 기본 포커스가 JSON일 때 추가 벨과 휘파람이 산만해질 수 있습니다.
Jayrock을 사용하여 .NET에서 JSON으로 작업하는 것은 .NET Framework XmlWriter, XmlReader 및 XmlSerializer 클래스를 통해 XML로 작업하는 것과 비슷합니다. Jayrock에 있는 JsonWriter, JsonReader, JsonTextWriter 및 JsonTextReader 클래스는 .NET Framework 클래스 XmlWriter, XmlReader, XmlTextWriter 및 XmlTextReader의 의미 체계를 모방합니다. 이러한 클래스는 하위 및 스트림 지향 수준에서 JSON과 상호 작용하는 데 유용합니다. 이러한 클래스를 사용하여 일련의 메서드 호출을 통해 JSON 텍스트를 만들거나 증분 구문 분석할 수 있습니다. 예를 들어 JsonWriter 클래스 메서드 WriteNumber(number) 를 사용하면 JSON 표준에 따라 적절한 숫자 문자열 표현을 작성합니다. JsonConvert 클래스는 .NET 형식과 JSON 간에 변환하기 위한 내보내기 및 가져오기 메서드를 제공합니다. 이러한 메서드는 각각 Serialize 및 Deserialize XmlSerializer 클래스 메서드에 있는 것과 유사한 기능을 제공합니다.
JSON 텍스트 만들기
다음 코드에서는 JsonTextWriter 클래스를 사용하여 대륙의 문자열 배열에 대한 JSON 텍스트를 만드는 방법을 보여 줍니다. 이 JSON 텍스트는 생성자에 전달된 TextWriter instance 전송됩니다. 이 예제에서는 콘솔의 출력 스트림이 됩니다(ASP.NET Response.Output을 대신 사용할 수 있음).
using (JsonTextWriter writer = JsonTextWriter(Console.Out))
{
writer.WriteStartArray();
writer.WriteString("Europe");
writer.WriteString("Asia");
writer.WriteString("Australia");
writer.WriteString("Antarctica");
writer.WriteString("North America");
writer.WriteString("South America");
writer.WriteString("Africa");
writer.WriteEndArray();
}
WriteStartArray, WriteString 및 WriteEndArray 메서드 외에도 JsonWriter 클래스는 WriteNumber, WriteBoolean, WriteNull 등과 같은 다른 JSON 값 형식을 작성하는 메서드를 제공합니다. WriteStartObject, WriteEndObject 및 WriteMember 메서드는 개체에 대한 JSON 텍스트를 만듭니다. 다음 예제에서는 "JavaScript에서 리터럴 표기법 이해" 섹션에서 검사된 연락처 개체에 대한 JSON 텍스트를 만드는 방법을 보여 줍니다.
private static void WriteContact() { using (JsonWriter w = new JsonTextWriter(Console.Out)) { w.WriteStartObject(); // { w.WriteMember("Name"); // "Name" : w.WriteString("John Doe"); // "John Doe", w.WriteMember("PermissionToCall"); // "PermissionToCall" : w.WriteBoolean(true); // true, w.WriteMember("PhoneNumbers"); // "PhoneNumbers" : w.WriteStartArray(); // [ WritePhoneNumber(w, // { "Location": "Home", "Home" // "Number": "555-555-1234"); // "555-555-1234" }, WritePhoneNumber(w, // { "Location": "Work", "Work", // "Number": "555-555-9999"); // "555-555-9999" } w.WriteEndArray(); // ] w.WriteEndObject(); // } } } private static void WritePhoneNumber(JsonWriter w, string location, string number) { w.WriteStartObject(); // { w.WriteMember("Location"); // "Location" : w.WriteString(location); // "...", w.WriteMember("Number"); // "Number" : w.WriteString(number); // "..." w.WriteEndObject(); // } }
JsonConvert 클래스의 Export 및 ExportToString 메서드를 사용하여 지정된 .NET 형식을 JSON 텍스트로 직렬화할 수 있습니다. 예를 들어 JsonTextWriter 클래스를 사용하여 7개 대륙의 배열에 대한 JSON 텍스트를 수동으로 빌드 하는 대신 JsonConvert.ExportToString 에 대한 다음 호출은 동일한 결과를 생성합니다.
string[] continents = { "Europe", "Asia", "Australia", "Antarctica", "North America", "South America", "Africa" }; string jsonText = JsonConvert.ExportToString(continents);
JSON 텍스트 구문 분석
JsonTextReader 클래스는 JSON 텍스트의 토큰을 읽기 키로 구문 분석하는 다양한 메서드를 제공합니다. Read 메서드가 호출될 때마다 파서는 문자열 값, 숫자 값, 개체 멤버 이름, 배열 시작 등과 같은 다음 토큰을 사용합니다. 해당하는 경우 Text 속성을 통해 현재 토큰의 구문 분석된 텍스트 에 액세스할 수 있습니다. 예를 들어 판독기가 부울 데이터에 있는 경우 Text 속성은 실제 구문 분석 값에 따라 "true" 또는 "false"를 반환합니다.
다음 샘플 코드는 JsonTextReader 클래스를 사용하여 7개 대륙의 이름을 포함하는 문자열 배열의 JSON 텍스트 표현을 구문 분석합니다. 문자 "A"로 시작하는 각 대륙은 콘솔로 전송됩니다.
string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
""North America"", ""South America"", ""Africa""]";
using (JsonTextReader reader = new JsonTextReader(new
StringReader(jsonText)))
{
while (reader.Read())
{
if (reader.TokenClass == JsonTokenClass.String &&
reader.Text.StartsWith("A"))
{
Console.WriteLine(reader.Text);
}
}
}
참고 Jayrock의 JsonTextReader 클래스는 상당히 자유로운 JSON 텍스트 파서입니다. 실제로 RFC 4627에 규정된 규칙에 따라 유효한 JSON 텍스트로 간주되는 것보다 훨씬 더 많은 구문을 허용합니다. 예를 들어 JsonTextReader 클래스를 사용하면 JavaScript에서 예상한 대로 JSON 텍스트 내에 한 줄 및 여러 줄 주석이 표시되도록 할 수 있습니다. 한 줄 주석은 슬래시(//)로 시작하고 여러 줄 주석은 슬래시 star(/*)로 시작하고 star 슬래시(*/)로 끝납니다. 한 줄 주석은 Unix 스타일 구성 파일에서 흔히 볼 수 있는 해시/파운드 기호(#)로 시작할 수도 있습니다. 모든 인스턴스에서 주석은 파서에서 완전히 건너뛰고 API를 통해 노출되지 않습니다. 또한 JavaScript에서와 같이 JsonTextReader 는 JSON 문자열을 아포스트로피(')로 구분할 수 있도록 허용합니다. 파서는 배열의 개체 또는 요소의 마지막 멤버 다음에 추가 쉼표도 허용할 수 있습니다.
이러한 모든 추가에도 불구하고 JsonTextReader 는 준수 파서입니다! 반면 JsonTextWriter는 엄격한 표준 준수 JSON 텍스트만 생성합니다. 이는 종종 견고성 주체로 만들어지는 것을 따르며, "여러분이 하는 일에 보수적이어야 합니다. 다른 사람에게서 받아들이는 것에 자유로울 수 있어야 합니다."
JSON 텍스트를 직접 .NET 개체로 변환하려면 JsonConvert 클래스 가져오기 메서드를 사용하여 출력 형식 및 JSON 텍스트를 지정합니다. 다음 예제에서는 문자열의 JSON 배열을 .NET 문자열 배열로 변환하는 방법을 보여 줍니다.
string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"", ""North America"", ""South America"", ""Africa""]"; string[] continents = (string[]) JsonConvert.Import(typeof(string[]), jsonText);
다음은 RSS XML 피드를 사용하고 XmlSerializer를 사용하여 .NET 형식으로 역직렬화한 다음 JsonConvert 를 사용하여 개체를 JSON 텍스트로 변환하는 변환의 더 흥미로운 예입니다(XML의 RSS를 JSON 텍스트로 효과적으로 변환).
XmlSerializer serializer = new XmlSerializer(typeof(RichSiteSummary)); RichSiteSummary news; // Get the MSDN RSS feed and deserialize it... using (XmlReader reader = XmlReader.Create("https://msdn.microsoft.com/rss.xml")) news = (RichSiteSummary) serializer.Deserialize(reader); // Export the RichSiteSummary object as JSON text, emitting the output to // Console.Out. using (JsonTextWriter writer = new JsonTextWriter(Console.Out)) JsonConvert.Export(news, writer);
참고RichSiteSummary 및 관련 형식의 정의는 이 문서와 함께 제공되는 샘플에서 찾을 수 있습니다.
ASP.NET JSON 사용
JavaScript에서 JSON으로 작업하고 Jayrock을 사용하여 .NET Framework 내에서 작업하는 방법을 살펴본 후에는 이 모든 지식을 적용할 수 있는 위치와 방법에 대한 실용적인 예제로 전환해야 합니다. 웹 브라우저에서 ASP.NET 페이지(또는 페이지의 특정 컨트롤)로 대역 외 호출을 수행하는 프로세스를 간소화하는 ASP.NET 2.0의 클라이언트 스크립트 콜백 기능을 고려합니다. 일반적인 콜백 시나리오에서 브라우저의 클라이언트 쪽 스크립트는 서버 쪽 메서드를 통해 일부 처리를 위해 웹 서버로 데이터를 패키지하고 다시 보냅니다. 서버에서 응답 데이터를 받은 후 클라이언트는 이를 사용하여 브라우저 디스플레이를 업데이트합니다.
참고 자세한 내용은 MSDN Magazine 문서 ASP.NET 2.0의 스크립트 콜백에서 찾을 수 있습니다.
클라이언트 콜백 시나리오의 과제는 클라이언트와 서버가 문자열만 앞뒤로 발송할 수 있다는 것입니다. 따라서 교환할 정보는 전송되기 전에 네이티브 메모리 내 표현에서 문자열로 변환한 다음, 수신될 때 문자열에서 네이티브 메모리 내 표현으로 다시 구문 분석해야 합니다. ASP.NET 2.0의 클라이언트 스크립트 콜백 기능은 교환된 데이터에 특정 문자열 형식이 필요하지 않으며 네이티브 메모리 내 표현과 문자열 표현 간에 변환하기 위한 기본 제공 기능을 제공하지도 않습니다. 선택한 데이터 교환 형식을 기반으로 변환 논리를 구현하는 것은 개발자의 달려 있습니다.
다음 예제에서는 클라이언트 스크립트 콜백 시나리오에서 JSON을 데이터 교환 형식으로 사용하는 방법을 보여 줍니다. 특히 이 예제는 Northwind 데이터베이스의 데이터를 사용하여 드롭다운 목록에서 범주 목록을 제공하는 ASP.NET 페이지로 구성됩니다. 선택한 범주의 제품이 글머리 기호 목록에 표시됩니다(그림 3 참조). 클라이언트 쪽에서 드롭다운 목록이 변경될 때마다 단일 요소가 선택한 CategoryID인 배열에 콜백이 전달됩니다.
참고 JSON 표준은 JSON 텍스트에 개체 또는 배열을 루트로 포함해야 하므로 선택한 CategoryID 를 유일한 요소( CategoryID가 아닌)로 포함하는 배열을 전달합니다. 물론 클라이언트가 JSON 텍스트를 서버에 전달할 필요는 없습니다. 이 예제에서는 선택한 CategoryID 만 문자열로 전달했을 수 있습니다. 그러나 콜백의 요청 및 응답 메시지 모두에서 JSON 텍스트를 보내는 방법을 보여 주고자 했습니다.
Page_Load 이벤트 처리기의 다음 코드는 범주 DropDownList 웹 컨트롤을 구성하여 변경되면 GetProductsForCategory 함수가 호출되고 선택한 드롭다운 목록 값을 전달합니다. 이 함수는 전달된 드롭다운 목록 값이 0보다 큰 경우 클라이언트 스크립트 콜백을 시작합니다.
// Add client-side onchange event to drop-down list
Categories.Attributes["onchange"] = "Categories_onchange(this);";
// Generate the callback script
string callbackScript = ClientScript.GetCallbackEventReference(
/* control */ this,
/* argument */ "'[' + categoryID + ']'",
/* clientCallback */ "showProducts",
/* context */ "null");
// Add the Categories_onchange function
ClientScript.RegisterClientScriptBlock(GetType(),
"Categories_onchange", @"
function Categories_onchange(sender)
{
clearResults();
var categoryID = sender.value;
if (categoryID > 0)
{
" + callbackScript + @"
}
}", true);
콜백을 호출하는 JavaScript 코드를 생성하는 데 사용되는 ClientScriptManager 클래스의 GetCallBackEventReference 메서드에는 다음 서명이 있습니다.
public string GetCallbackEventReference (
Control control,
string argument,
string clientCallback,
string context,
)
인수 매개 변수는 콜백 중에 클라이언트에서 웹 서버로 전송되는 데이터를 지정하고 clientCallback 매개 변수는 콜백 완료 시 호출할 클라이언트 쪽 함수의 이름(showProducts)을 지정합니다. GetCallBackEventReference 메서드 호출은 다음 JavaScript 코드를 생성하고 렌더링된 태그에 추가합니다.
WebForm_DoCallback('__Page','[' + categoryID +
']',showProducts,null,null,false)
'[' + categoryID + ']' 는 콜백 중에 서버에 전달되는 값(단일 요소인 categoryID가 있는 배열)이며 showProducts 는 콜백이 반환될 때 실행되는 JavaScript 함수입니다.
서버 쪽에서 콜백에 대한 응답으로 실행되는 메서드는 Jayrock의 JsonConvert 클래스를 사용하여 들어오는 JSON 텍스트를 구문 분석하고 나가는 JSON 텍스트의 서식을 지정합니다. 특히 선택한 범주와 연결된 제품의 이름이 검색되어 문자열 배열로 반환됩니다.
// Deserialize the JSON text into an array of integers int[] args = (int[]) JsonConvert.Import(typeof(int[]), eventArgument); // Read the selected CategoryID from the array int categoryID = args[0]; // Get products based on categoryID
NorthwindDataSet.ProductsRow[] rows = Northwind.Categories.FindByCategoryID(categoryID).GetProductsRows();// Load the names into a string array
string[] productNames = new string[rows.Length]; for (int i = 0; i < rows.Length; i++) { productNames[i] = rows[i].ProductName;}
// Serialize the string array as JSON text and return it to the client
return JsonConvert.ExportToString(productNames);
참고JsonConvert 클래스는 두 번 사용됩니다. 한 번은 eventArgument 의 JSON 텍스트를 정수 배열로 변환한 다음 문자열 배열 productNames를 JSON 텍스트로 변환하여 클라이언트로 돌아갑니다. 또는 여기에서 JsonReader 및 JsonWriter 클래스를 사용할 수 있었지만 관련된 데이터가 상대적으로 작고 기존 형식에 쉽게 매핑될 때 JsonConvert 는 동일한 작업을 상당히 잘 수행합니다.
데이터가 서버 쪽에서 반환되면 GetCallBackEventReference 메서드에서 지정된 JavaScript 함수가 호출되고 반환 값이 전달됩니다. 이 JavaScript 메서드 showProducts는 div> 요소 ProductOutput을 참조하여< 시작합니다. 그런 다음 JSON 응답을 구문 분석하고 각 배열 요소에 대한 목록 항목을 사용하여 순서가 지정되지 않은 목록을 동적으로 추가합니다. 선택한 범주에 대해 반환되는 제품이 없으면 해당 메시지가 대신 표시됩니다.
function showProducts(arg, context) { // Dump the JSON text response from the server. document.forms[0].JSONResponse.value = arg; // Parse JSON text returned from callback. var categoryProducts = eval("(" + arg + ")"); // Get a reference to the <div> ProductOutput. var output = document.getElementById("ProductOutput"); // If no products for category, show message. if (categoryProducts.length == 0) { output.appendChild(document.createTextNode( "There are no products for this category...")); } else { // There are products, display them in an unordered list. var ul = document.createElement("ul"); for (var i = 0; i < categoryProducts.length; i++) { var product = categoryProducts[i]; var li = document.createElement("li"); li.appendChild(document.createTextNode(product)); ul.appendChild(li); } output.appendChild(ul); } }
그림 2에서는 이벤트 시퀀스를 보여 주며 그림 3에서는 이 예제가 실제로 작동하는 것을 보여 줍니다. 전체 코드는 이 문서 다운로드에 포함되어 있습니다.
그림 2: 클라이언트는 선택한 CategoryID를 배열의 단일 요소로 보내고 서버는 연결된 제품 이름의 배열을 반환합니다.
그림 3: 선택한 범주 내의 글머리 기호 목록에 제품이 표시됩니다.
결론
JSON은 JavaScript 프로그래밍 언어의 리터럴 표기법 하위 집합을 기반으로 하는 간단한 텍스트 기반 데이터 교환 형식입니다. 애플리케이션 데이터 구조에 대한 간결한 인코딩을 제공하며 일반적으로 Ajax 스타일 웹 애플리케이션과 같이 데이터를 교환하는 애플리케이션 중 하나 또는 둘 다에서 JavaScript 구현을 사용할 수 있는 시나리오에서 사용됩니다. JSON의 매력은 이해하기, 채택 및 구현하기 위한 단순성입니다. JSON에는 JavaScript 또는 풍부한 리터럴 표기법(예: Python 및 Ruby)에 대해 유사한 지원을 사용하는 다른 프로그래밍 언어에 이미 익숙한 개발자를 위한 학습 곡선이 거의 없습니다. JavaScript 코드에서 JSON 텍스트를 구문 분석하려면 eval 함수를 호출하기만 하면 됩니다. JSON 텍스트를 만드는 것은 에서 http://www.json.org/json.js제공하는 json.js 스크립트를 사용하여 간단하게 수행할 수 있습니다.
모든 주요 플랫폼 및 프레임워크에서 JSON을 사용하기 위한 수많은 라이브러리가 있습니다. 이 문서에서는 .NET 애플리케이션에서 JSON 텍스트를 만들고 구문 분석하기 위한 오픈 소스 라이브러리인 Jayrock을 살펴보았습니다. Jayrock은 ASP.NET 1.x, 2.0 및 Mono 애플리케이션에서 사용할 수 있습니다. ASP.NET AJAX는 유사한 JSON 기능을 제공하지만 ASP.NET 2.0 애플리케이션에만 해당합니다.
행복한 프로그래밍!
참조
- ASP.NET AJAX
- AJAX 확장을 사용하는 클라이언트 쪽 웹 서비스 호출
- 핵심 JavaScript 1.5 가이드
- eval(expr) 함수
- Jayrock
- JSON.org
- ASP.NET 콜백 스크립팅
- RFC 4627
아약스 또는 AJAX?
Ajax라는 용어는 처음에 Jesse James Garrett 가 웹 애플리케이션의 스타일과 고도로 대화형 웹 애플리케이션을 만드는 데 관련된 기술 세트를 설명하기 위해 만들어졌습니다. 지금까지 Ajax라는 용어는 비동기 JavaScript 및 XML을 의미하는 약어 AJAX로 웹에 퍼졌습니다. 그러나 시간이 지남에 따라 대부분의 구현이 더 간단하고 효율적인 대안으로 JSON으로 전환되었기 때문에 AJAX의 "X"가 백그라운드에서 웹 서버와 통신하는 데 사용되는 기본 데이터 형식을 대표하지 않는다는 것을 깨달았습니다. 따라서 혀 트위스터의 비트인 AJAJ와 같은 대체 약어를 마련하는 대신, 약어는 일반적으로 AJAX 약어가 아닌 아약스를 위해 사용 중지됩니다.
이 글의 시간에, 하나 같은 것을 의미하는 "AJAX"와 "Ajax"의 혼합 및 넓은 사용을 볼 것으로 예상. 이 문서에서는 "Ajax 용어"를 고수했습니다. 그러나 Ajax 스타일의 애플리케이션을 가능하게 하는 프레임워크를 제공하는 상용 제품은 비슷한 이름의 청소 에이전트 제품과 구별하고 잠재적인 상표 또는 법적 분쟁을 피하기 위해 머리글자어 형식을 사용하는 경향이 있습니다.
ASP.NET AJAX: JSON 날짜 및 시간 문자열 내부
ASP.NET AJAX JSON 직렬 변환기는 DateTime instance JSON 문자열로 인코딩합니다. 시험판 주기 동안 ASP.NET AJAX는 "@ticks@" 형식을 사용했습니다. 여기서 틱은 UTC(Universal Coordinated Time)에서 1970년 1월 1일 이후의 밀리초 수를 나타냅니다. UTC(예: 1989년 11월 29일, 오전 4:55:30)와 같은 날짜 및 시간은 "@62831853071@"로 작성됩니다. 단순하고 간단하지만 이 형식은 직렬화된 날짜 및 시간 값과 직렬화된 날짜처럼 보이지만 역직렬화할 수 없는 문자열을 구분할 수 없습니다. 따라서 ASP.NET AJAX 팀은 "\/Date(ticks)\/" 형식을 채택하여 이 문제를 해결하기 위해 최종 릴리스를 변경했습니다.
새 형식은 작은 트릭을 사용하여 잘못된 해석 가능성을 줄입니다. JSON에서 문자열의 슬래시(/) 문자는 반드시 필요하지 않더라도 백슬래시(\)로 이스케이프할 수 있습니다. 이를 활용하여 ASP.NET AJAX 팀은 JavaScriptSerializer를 수정하여 DateTime instance 대신 "\/Date(ticks)\/" 문자열로 작성했습니다. 두 슬래시의 이스케이프는 피상적이지만 JavaScriptSerializer에 중요합니다. JSON 규칙에
"
따라 \/Date(ticks)\/"
는 기술적으로 /Date(ticks)/와"
동일"
하지만 JavaScriptSerializer는 전자를 DateTime으로 역직렬화하고 후자는 String으로 역직렬화합니다. 따라서 사전 릴리스의 간단한 "@ticks@" 형식과 비교할 때 모호성 가능성이 상당히 적습니다.
특별 감사
이 문서를 MSDN에 제출하기 전에 많은 지원자가 문서를 교정하고 콘텐츠, 문법 및 방향에 대한 피드백을 제공하는 데 도움을 주었습니다. 검토 프로세스의 주요 기여자로는 더글러스 크록포드, 에릭 숀홀처, 밀라노 네고반 등이 있습니다.
저자 정보
Atif Aziz는 Skybow AG의 수석 컨설턴트로, 고객이 .NET 개발 플랫폼에서 솔루션을 이해하고 빌드할 수 있도록 돕는 데 중점을 둡니다. Atif는 컨퍼런스에서 연설하고 기술 출판물에 대한 문서를 작성하여 Microsoft 개발자 커뮤니티에 정기적으로 기여합니다. 그는 INETA 연사이자 가장 큰 스위스 .NET 사용자 그룹의 사장입니다. 그는 에서 atif.aziz@skybow.com 또는 에서 자신의 웹 사이트를 http://www.raboof.com통해 도달 할 수 있습니다.
6개의 ASP/ASP.NET 책의 저자이자 4GuysFromRolla.com 창립자인 Scott Mitchell은 1998년부터 Microsoft 웹 기술을 사용하고 있습니다. Scott은 독립 컨설턴트, 트레이너 및 작가로 일합니다. 그는 또는 그의 블로그를 mitchell@4guysfromrolla.com 통해 도달 할 수 있습니다 : http://ScottOnWriting.net.