Atom 문서를 JSON으로 변환하기 (한글) :: 에이젝스 일반[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

에이젝스 일반
[1]
등록일:2008-04-02 15:14:36 (0%)
작성자:
제목:Atom 문서를 JSON으로 변환하기 (한글)

Atom에서 JSON으로 변환할 때 중요한 데이터와 콘텍스트의 손실 피하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

수평출력으로 설정

이 페이지 출력

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

토론

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

James Snell, Software Engineer, Emerging Technologies, IBM

2008 년 2 월 19 일

Atom 문서를 JSON으로 변환하는 일은 언뜻 보기에는 매우 단순한 일처럼 보입니다. Atom은 단순한 XML 조각이고, XML-JSON 변환 툴은 많이 있기 때문입니다. 하지만, Atom 포맷은 단순한 XML 엘리먼트와 애트리뷰트 만은 아닙니다. 많은 미묘한 상세들 때문에 Atom을 다루는 일이 까다롭습니다. 이 글에서는 그러한 문제들을 짚어보고, Apache Abdera 프로젝트에서 구현된 메커니즘으로 Atom 문서를 JSON으로 변환하는 방법을 설명합니다.

여러분이 Atom 문서를 JSON으로 변환할 때, 많은 정보를 가진 콘텐트를 가져다가 이를 완전히 단순화된 폼으로 직렬화 한다. XML의 파싱과 적절한 처리가 매우 어려운 환경에서 이러한 콘텐트를 보다 쉽게 사용할 수 있다. 이러한 프로세스의 가장 주요한 문제는 중요한 데이터와 정황이 변환 시 소실되지 않게 하는 것이다. 이 글을 읽고 있는 여러분은 Atom과 JSON을 기본적으로 이해하고 있어야 한다. 이 두 가지에 익숙하지 않다면, 시간을 내어 참고자료 섹션을 읽어보기 바란다.

언어 메타데이터

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

Atom 문서에는 인간과 머신에 의해 소비될 혼합된 정보가 포함되어 있다. 엔트리의 제목, 카테고리 레이블, 링크 제목, 권한 설명 등 인간이 읽을 수 있는 콘텐트를 적절하게 나타내는 것은 JSON으로 변형 동안에 올바르게 보존되어야 하는 언어 정황에 의존하고 있다.

애트리뷰트는 Atom 문서 어디에나 나타날 수 있고, 자식 엘리먼트에 의해 상속 또는 오버라이드 될 수 있다. xml:lang 애트리뷰트의 값은 RFC 4646, "Tags for Identifying Languages" 에 의해 정의된 것처럼 "Language Tag" 이다. 이러한 태그는 텍스트를 작성한 언어, 사용된 스크립트나 작성 시스템, 지역 언어 등에 대한 정보를 제공한다. 이와 같은 정보는 사용자-에이전트에 의해 텍스트가 나타나는 방식에 영향을 미친다.

Listing 1의 Atom 피드 예제는 다소 말이 안되는 부분이 있지만, Atom 문서 내의 xml:lang의 사용법을 나타내고 있다.


Listing 1. xml:lang을 사용하는 Atom 피드
                
<feed xmlns="http://www.w3.org/2005/Atom"
xml:lang="en-US">
<title>This is the title</title>
...
<entry xml:lang="fr">
...
<category term="foo" label="bar" xml:lang="en" />
<category term="goo" label="baz" />
...
</entry>
</feed>

피 드 엘리먼트에 대한 xml:lang 애트리뷰트는 전체 문서에 대한 기본 언어 정황을 확립한다. xml:lang을 명확하게 오버라이드 하지 않는 자식 엘리먼트(예를 들어, 피드의 title 엘리먼트)는 자동으로 그 언어를 상속받는다.

직렬화된 JSON에서, 언어 정황은 xml:lang 애트리뷰트를 필드로 변환함으로써 알 수 있다. 변형 규칙은 간단하다: 언어 정황이 변할 때마다 단일 lang을 출력하는 것이다. Listing 2는 Listing 1의 피드의 직렬화를 보여준다. lang 필드는 feed, entry, 첫 번째 category를 위해 등장하지만, title과 두 번째 category에서는 생략된다. 이는 후자의 엘리먼트들이 부모 엘리먼트의 언어를 상속받기 때문이다.


Listing 2. Listing 1에 있는 피드의 JSON 직렬화
                
{
"lang":"en-US",
"title":"This is the title",
"entries":[
{
"lang":"fr"
"categories":[
{
"lang":"en",
"term":"foo",
"label":"bar"
},
{
"term":"goo",
"label":"baz"
}
]
}
]
}

xml:lang 애트리뷰트는 자식 또는 애트리뷰트가 Language Sensitive인 것으로 간주되는 엘리먼트에 나타날 수 있다. Atom 핵심 어휘 내에서 이러한 설정에는 feed, entry, title, rights, subtitle, summary, content, category, link, author, contributor가 포함된다.




위로


IRI와 URI

다중 언어에 대한 지원 외에도 Atom은 Internationalized Resource Identifiers(IRI)의 사용을 지원한다. IRI는 비 ASCII 문자들을 포함시킬 수 있는 URI이다.

Atom-JSON 직렬화를 디자인 할 때, Atom 문서 내에서 두 개의 IRI 사용법들을 구분하는 것이 중요하다. Listing 3의 예제에서, 네 개의 엘리먼트에 IRI의 엘리먼트가 포함되어 있다.


Listing 3. 다중 Internationalized Resource Identifiers를 포함하고 있는 피드
                
<feed xmlns:a="http://www.w3.org/2005/Atom"
xml:base="http://examplé
.org/fo
ó">
...
<id>http://examplé
.org/fo
ó</id>
<link rel="self" href="" />
<link href="/blog" />
<category scheme="http://examplé
.org/fo
ó/bar" term="foo" />
...
</feed>

id 와 category 에리먼트는 구분자로서 IRI를 사용한다. 보통 URL처럼 보인다는 사실에도 불구하고, 이 같은 구분자들은 접근성이 없다. Atom은 이러한 방식으로 사용되는 IRI가 절대적인 것으로 되어야 하며, 일반적으로 이들을 Atom 소비자들의 일부에 대한 별도의 추가 프로세싱이 필요하지 않는 불분명한 값으로서 취급한다. Atom 어휘 내에서, id와 category는 IRI를 구분자로서 사용하는 유일한 엘리먼트이다.

하지만 link 엘리먼트는 일부 다른 리소스에 대한 리소스를 제공한다. href 애트리뷰트는 접근될 수 있는 IRI를 설정해야 한다. 애트리뷰트의 값은 상대 경로가 될 수 있고, Atom 소비자들에 의해 처리되어 정확한 결과를 내야 한다. 이와 같은 프로세싱에는 IRI를 동등한 URL로 변환하는 것이 포함된다. Atom 핵심 어휘 내에서, icon, logo, uri, link, content 엘리먼트에 접근할 수 있는 IRI가 포함될 수 있다.

Listing 4는 id와 category 엘리먼트의 JSON 직렬화를 보여준다. IRI는 추가 프로세싱 없이, 있는 그대로 복사되었다.


Listing 4. Listing 3의 id와 category 엘리먼트의 JSON 직렬화
                
"id":"http://examplé
.org/fo
ó"
"categories":[
{
"scheme":"http://examplé
.org/fo
ó/bar",
"term":"foo"
}
]

한 편 접근 가능한 IRI는 완전한 이름의 절대 경로로 변환되어야 하고, JSON 내에서 사용할 수 있는 URL로 변환되어야 한다. (Listing 5) "http://xn--exampl-gva.org/fo%C3%B3"은 IRI "http://examplé.org/foó"에 해당하는 ASCII URL이다.


Listing 5. Listing 3의 link 엘리먼트의 JSON 직렬화
                
"links":[
{
"rel":"self",
"href":"http://xn--exampl-gva.org/fo%C3%B3"
},
{
"href":"http://xn--exampl-gva.org/blog"
}
]

Atom 문서 내 어디에나 나타나는 접근 가능한 IRI나 URI에는 비슷한 처치가 주어져야 하는데, Listing 6처럼 텍스트 구조체와 콘텐트에 HTML과 XHTML 마크업 내에 나타나는 것에는 더욱 그렇다.


Listing 6. URI 상대 경로를 포함하고 있는 XHTML 마크업
                
<a:content type="xhtml">
<div>
<img src="/images/foo.jpg" />
</div>
</a:content>

JSON 은 Base URI의 개념을 갖고 있을 수 없기 때문에, JSON 직렬화를 사용하는 애플리케이션은 상대 URI 경로를 포함하고 있는 마크업을 올바르게 실행할 수 있다. 따라서, Listing 7에서 보듯, 변환 프로세스 동안 이와 같은 경로들이 자동으로 변환되어야 한다.


Listing 7. Listing 6의 XHTML 마크업의 JSON 직렬화
                
"content":{
"attributes":{
"type":"xhtml"
},
"children":[
{
"name":"img",
"attributes":{
"src":"http://example.org/images/foo.jpg"
},
"children":[]
}
]
}

여기에는 HTML과 XHTML 마크업을 올바르게 파싱하고 값이 URI가 될 수 있는 애트리뷰트를 선택할 수 있도록 직렬화된 JSON 아웃풋을 만들어 내는 애플리케이션을 필요로 한다.




위로


반복 가능한 엘리먼트

Atom 어휘 내에 여러 엘리먼트들은 피드나 엔트리 내에서 한 번 이상 나타날 수 있다. JSON 직렬화에서, 이들은 Listing 8과 9처럼, Array로서 실행된다.


Listing 8. Atom feed, entry, source 엘리먼트들은 여러 atom:author 엘리먼트들을 포함할 수 있다.
                
<author>
<name>James M Snell</name>
</author>
<author>
<name>Jane Doe</name>
</author>


Listing 9. Listing 8에 있는 author 엘리먼트의 JSON 직렬화
                
"authors":[
{
"name":"James M Snell",
},
{
"name":"Jane Doe",
}
]

Atom 어휘 내에서, author, contributor, category, entry 엘리먼트 모두 반복 가능하다. Listing 10부터 13까지는 반복 가능한 엘리먼트들을 JSON 어레이로 변환하는 것을 보여준다. 이 예제는 읽어보면 알 수 있다. 상세한 내용은 설명하지 않겠다.


Listing 10. 여러 Atom category 엘리먼트
                
<category term="foo"
scheme="http://example.org/categories/" />
<category term="bar"
scheme="http://example.org/categories/"
label="Bar" />


Listing 11. Listing 10의 다중 category 엘리먼트의 JSON 직렬화
                
"categories":[
{
"term":"foo",
"scheme":"http://example.org/categories/"
},
{
"term":"bar",
"scheme":"http://example.org/categories/",
"label":"Bar"
}
]


Listing 12. 다중 Atom link 엘리먼트
                
<link href="/foo"
rel="related"
title="Related Entry"
type="text/html" />
<link href="/bar"
title=”Alternate View"
type="text/html" />


Listing 13. Listing 10의 다중 link 엘리먼트의 JSON 직렬화
                
"links":[
{
"href":"http://example.org/foo",
"rel":"related",
"title":"Related Entry",
"type":"text/html"
},
{
"href":"http://example.com/bar",
"title":"Alternate View",
"type":"text/html"
}
]




위로


Dates

Atom 내에 Date와 times는 RFC 3339에 의해 지정된 ISO 8601 포맷의 하위 세트를 사용하여 나타난다. Listing 14는 Atom 업데이트 엘리먼트의 예제를 보여준다.


Listing 14. Atom 업데이트 엘리먼트의 RFC 3339 date-time
                
<updated>2007-10-14T12:12:12Z</updated>

JSON의 데이터 타이핑 모델 때문에, Date를 직렬화 할 때 한정된 범위의 옵션들을 갖고 있다. 필자는 다음 중 하나만 할 수 있다:

  • 1970년 1월 1일 한밤중의 UTC 이후의 흘러간 초(second)를 가리키는 숫자 값으로 Date를 변환한다. (예를 들어, 표준 유닉스® 타임스탬프)
  • Date를 JavaScript toString 날짜 직렬화로 변환한다. (예, Sun Oct 21 2007 12:34:28 GMT-0700 (PDT))
  • Atom 문서 내에 나타나는 것과 똑같이 Date를 복사한다.

처 음 두 옵션들은 개발자로서 많은 일을 하지 않고 JavaScript 내에서 작업할 수 있다는 이점이 있다. 다시 말하면, 올바른 JavaScript Date 객체를 얻기 위해서는, 새로운 Date(feed.updated)를 호출할 수 있다. 하지만, 단점은 첫 번째 옵션으로는 밀리초와 timezone 오프셋에 대한 중요한 정보가 소실될 수 있다는 점이다. 그리고, 두 번째 옵션으로는 Date의 toString 직렬화가 구현과 로케일에 따라 달라질 수 있다. RFC 3339 직렬화를 사용하려면 추가 작업이 필요하지만, 데이터 손실과 모호함을 피할 수 있는 유일한 옵션이다.


Listing 15. Listing 14의 업데이트 된 엘리먼트의 JSON 직렬화
                
"updated":"2007-10-14T12:12:12.000Z"

Listing 16의 JavaScript 코드는 RFC 3339 date-times를 파싱하고, 올바른 JavaScript Date 객체를 만들어 낸다.


Listing 16. Atom에서 사용될 때처럼 RFC 3339 date-times를 파싱하는 JavaScript 코드
                
AtomDate = Class.create();
AtomDate.pattern = /^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?(?:[Tt] \
(\d{2}):(\d{2}):(\d{2})(?:\.(\d*))?)?([Zz])?(?:([+-])(\d{2}):(\d{2}))?$/;
AtomDate.localoffset = (new Date()).getTimezoneOffset();
AtomDate.padding = function(val,char,count) {
var value = "";
while(count > 0) {
if (val < Math.pow(10,count)) value = char + value;
count--;
}
return value + val;
}
AtomDate.parse = function(val) {
if (!val) throw "Invalid Date";
if (val instanceof Date) return val;
var m = AtomDate.pattern.exec(val);
var year = new Number(m[1]?m[1]:0);
var month = new Number(m[2]?m[2]:0);
var day = new Number(m[3]?m[3]:0);
var hour = new Number(m[4]?m[4]:0);
var minute = new Number(m[5]?m[5]:0);
var second = new Number(m[6]?m[6]:0);
var millis = new Number(m[7]?m[7]:0);
var gmt = m[8];
var dir = m[9];
var offhour = new Number(m[10]?m[10]:0);
var offmin = new Number(m[11]?m[11]:0);

if (dir && offhour && offmin) {
var offset = ((offhour * 60) + offmin);
if (dir == "+") {
minute -= offset;
} else if (dir == "-") {
minute += offset;
}
}
return new Date(Date.UTC(year,month,day,hour,minute,second,millis));
}

Object.prototype.value2date = function() {
return AtomDate.parse(this);
}

value2date 함수는 값이 RFC 3339 date인 스트링 값을 JavaScript Date로 얻을 수 있다.

주: AtomDate.pattern의 정규식은 포맷팅을 위해 여러 라인들로 나뉜다.


Listing 17. Listing 16의 Date 파싱 코드 사용하기
                     
document.write(m.updated.value2date());




위로


텍스트 구조

광 범위한 텍스트와 콘텐트 옵션에 대한 Atom의 지원은 지금까지는 JSON 직렬화에서 권한을 얻기가 가장 복잡하고 어려운 문제였다. title, subtitle, summary, rights 엘리먼트 같은 텍스트 구조들에는 플레인 텍스트, escaped HTML 또는 XHTML 마크업이 포함될 수 있다. 이들은 언어에 민감하므로 xml:lang 콘텍스트가 고려되어야 한다. 그리고 HTML과 XHTML 마크업에는 변환되어야 하는 상대 URI가 포함될 수 있다. Atom 콘텐트 엘리먼트는 Base64 인코딩 콘텐트, 임의의 XML 마크업, src 애트리뷰트를 사용하여 참조되는 외부 콘텐트에 대한 지원을 없앴기 때문에 더욱 복잡해 졌다.

Atom 콘텐트의 JSON 직렬화의 목표는 가능한 일관성 있게 이러한 모든 옵션들을 포착하는 일반화 된 표현들을 찾는 것이다. Listing 18은 세 개의 텍스트 구조를 갖고 있는 예제 피드를 보여준다.


Listing 18. 세 개의 다른 유형의 텍스트 구조를 갖고 있는 Atom 피드 엘리먼트
                
<feed xmlns="http://www.w3.org/2005/Atom">
...
<title>Example Feed</title>
<subtitle type="html"><p>This is an example feed</p></subtitle>
<rights xml:lang="fr">...</right>
...
</feed>

title 엘리먼트는 플레인 텍스트로 간주된다. 이것은 피드의 언어 정황을 상속받고, 그렇지 않으면, 정체를 알 수 없는 막연한 것이다. subtitle 엘리먼트에는 escaped HTML 마크업이 포함된다. rights 엘리먼트는 플레인 텍스트이지만, 언어 정황을 오버라이드 한다. Listing 19는 이러한 세 개의 엘리먼트에 대한 JSON 직렬화이다.


Listing 19. Listing 18의 텍스트 구조에 대한 JSON 직렬화
                
{
"title":"Example Feed",
"subtitle":{
"attributes":{
"type":"html"
},
"children":[
{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
}
]
},
"rights":{
"attributes":{
"lang":"fr"
},
"children":[
"..."
]
}
}

가장 단순한 경우, title은 간단한 스트링으로 직렬화 된다. 하지만, 언어 정황은 rights 엘리먼트에서 변하기 때문에, 플레인 텍스트라 할 지라도, 두 개의 필드, 애트리뷰트, 자식들로 구성된 객체로 직렬화 된다.

subtitle 엘리먼트의 경우, HTML 마크업이 파싱되고 계층 구조로서 렌더링 된다. 같은 구조가 XHTML 마크업에 사용된다. (Listing 20과 21).


Listing 20. XHTML 마크업을 사용하는 텍스트 구조
                
<subtitle type="xhtml">
<div xmlns="..."><p>This is an example feed</p></div>
</subtitle>


Listing 21. Listing 20의 XHTML 마크업의 JSON 직렬화
                
"subtitle":{
"attributes":{ "type":"xhtml" },
"children":[
{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
}
]
}

이 구조는 플레인 텍스트와 마크업 콘텐트가 분명하고 일관된 방식으로 직렬화 된다는 것을 보장한다. 단점은 웹 브라우저에 콘텐트를 디스플레이 하는 것이 document.write(...) 를 수행하거나 div 상에 innerHTML 프로퍼티를 설정하는 것만큼 단순하지 않다는 것이다. 여러분에게 필요한 것은 파싱된 구조를 디스플레이 하기 쉬운 폼으로 변환하는 것이다.

Listing 22는 Sam Ruby에서 제공된 코드의 수정된 버전으로서, Atom 텍스트 구조 또는 content 엘리먼트의 JSON 직렬화를 취해서, 이를 스트링으로 변환한다.


Listing 22. JSON으로 직렬화 된 텍스트 구조를 디스플레이 가능한 스트링 값으로 재구현 하는 JavaScript
                
Array.prototype.hash2value = function () {
var result = '';
for (var i=0; this.length>=i; i++) if (this[i]) result+=this[i].tag2value();
return result;
}

Object.prototype.tag2value = function () {
if (this.name) {
var result = String.fromCharCode(60) + this.name;
for (key in this.attributes) {
if (typeof(this.attributes[key]) === 'function') continue;
result += ' ' + key + '="' + this.attributes[key].toString() + '"';
}
result += '>' + this.children.hash2value();
result += String.fromCharCode(60) + '/' + this.name + '>';
return result;
} else return this.toString();
}

Object.prototype.value = function() {
if (this.children) return this.children.hash2value();
else return this.toString();
}

Array.prototype.value = function() {
var result = '';
for (var i = 0; this.length>=i; i++)
if (this[i]) result+=this[i].value();
return result;
}

JavaScript Array와 Object 클래스에 추가된 value 함수는 특정 객체가 간단한 스트링 또는 객체 구조로 직렬화 되었는지 여부에 신경 쓰지 않고 hash2value 함수를 사용할 수 있도록 한다.


Listing 23. Listing 22의 JavaScript 코드를 사용하여 JSON 직렬화에서 텍스트 디스플레이 하기
                
document.write(m.title.value());
document.write(m.subtitle.value());
document.write(m.rights.value());

여 기에 제시된 모델을 사용하여, atom:content 엘리먼트 내 확장된 콘텐트 유형으로 작업하는 것은 플레인 텍스트, HTML, XHTML로 작업하는 것과 다르지 않다. Listing 24는 대안 미디어 유형, 임의의 XML, Base64 인코딩 바이너리 데이터, src 애트리뷰트를 사용하여 참조된 콘텐트의 사용법을 설명하는 네 개의 확장된 콘텐트 예제를 보여주고 있다.


Listing 24. 확장된 콘텐트 유형 예제
                     
<content type="text/plain">This is plain text</content>

<content type="application/xml"><a xmlns="foo">b</a></content>

<content type="image/jpg">{base64 encoded data}</content>

<content type="image/jpg" src="image.jpg" />

Listing 25는 이러한 콘텐트 폼에 대한 JSON 직렬화를 보여주고 있다.


Listing 25. Listing 24의 확장된 콘텐트 유형에 대한 JSON 직렬화
                
"content":{
"attributes":{ "type":"text/plain" },
"children":["This is plain text" ]
}

"content":{
"attributes":{ "type":"application/xml" },
"children":[
{
"name":"a",
"attributes": {
"xmlns":"foo"
},
"children":["b"]
}
]
}

"content":{
"attributes":{ "type":"image/jpg" },
"children":["{base64 encoded data}" ]
}

"content":{
"attributes":{
"type":"image/jpg",
"src":"http://example.org/image.jpg"
},
"children":["" ]
}




위로


확장

Atom을 JSON으로 직렬화 할 때 마지막으로 생각해야 할 부분은 확장을 다루는 방법이다. 세 가지 선택권이 있다:

  • 모든 확장을 무시하고, 이들을 JSON 직렬화에 포함시키지 말 것.
  • 알려진 확장을 직렬화 하고, 그 외 모든 것을 무시할 것.
  • 모든 확장을 직렬화 할 것.

첫 번째 선택권은 가장 쉬운 것이지만, JSON 표현의 유용성을 제한한다. (그렇다고 해서 이것이 나쁘다는 것은 아니다.) 두 번째 선택권은 알려진 확장에 대한 JSON 직렬화가 최적화 및 단순화 되도록 하지만, 직렬화의 유용성을 제한한다. 세 번째 옵션은 직렬화의 전체적인 복잡함을 늘리지만, 원래 Atom 문서의 모든 정보들이 JSON 표현을 통해 확실히 드러날 수 있다.

먼 저, 알려진 확장에 대한 아웃풋을 최적화 하는 방법을 보자. Atom Threading Extension (RFC 4685)은 하나의 엔트리가 다른 것에 대한 응답이라는 것을 가리키는 수단을 제공한다. 쓰레딩 확장에 대한 스팩은 애트리뷰트와 in-reply-to 엘리먼트의 의미를 명확하게 설정하고, 다중 in-reply-to 엘리먼트가 한 엔트리 내에 나타날 수 있다. 이를 기반으로, 여러분은 in-reply-to 엘리먼트의 최적화 된 JSON 표현을 만들 수 있는 것이다. (Listing 26, 27)


Listing 26. Atom Entry에 Atom Threading Extension 사용하기
                
<entry>
...
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/2" />
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/3" />
...
</entry>


Listing 27. Listing 26의 Atom Threading Extension의 JSON 직렬화
                
"inreplyto":[
{
"ref":"tag:example.org,2007:/foo/entries/2"
},
{
"ref":"tag:example.org,2007:/foo/entries/3"
}
]

For unknown extensions, however, you'll use a more verbose and generalized syntax to capture all of the necessary details. Listing 28 shows an example of an entry with a complex, unknown extension element.


Listing 28. Atom 엔트리의 복잡하고 알려지지 않은 확장
                
<entry>
...
<foo:a xmlns="..."><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
...
</entry>

확장의 직렬화(Listing 29)는 일반적으로 HTML 또는 XHTML 마크업으로 구성된 텍스트에 사용되는 것과 동일하다.


Listing 29. Listing 28의 확장에 대한 JSON 직렬화
                
"extensions":[
{
"name":"foo:a",
"attributes":{
"xmlns:foo":"http://example.org/unknown-markup"
},
"children":[
{
"name":"foo:b",
"attributes":{ },
"children":[
{
"name":"foo:c",
"attributes":{ "d":"e" },
"children":["f" ]
}
]
}
]
}
]




위로


정리

이 모든 것을 기반으로 Atom 문서를 가져다가 이를 유용한 JSON 표현으로 변환시킬 수 있다. Listing 30과 31은 변환 프로세스 전체를 설명한 것이다. 원래의 Atom 문서에는 상대 IRI, 언어 정황, 확장, 다양한 텍스트와 콘텐트 유형 등이 포함되어 있다. 이 문서를 인터넷 상에서 많은 XML-JSON 컨버터를 통해 실행하면 데이터 손실 또는 심각한 가용성 문제로 무한 고통을 받는 직렬화가 될 것이다.


Listing 30. 전체 Atom 피드 문서
                
<?xml version="1.0" encoding="utf-8" ?>
<a:feed xmlns:a="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:foo="http://example.org/unknown-markup"
xml:lang="en-US"
xml:base="http://example.org/foo"
dir="ltr">

<a:id>tag:example.org,2007:/foo</a:id>
<a:title>Example Feed</a:title>
<a:subtitle type="html"><![CDATA[<p>This is an example feed</p>]]></a:subtitle>
<a:rights type="xhtml">
<div>
<p>Copyright © James M Snell</p>
</div>
</a:rights>
<a:author xmlns="http://www.w3.org/2005/Atom">
<name>James M Snell</name>
<email>jasnell@example.org</email>
<uri>/~jasnell</uri>
</a:author>
<a:updated>2007-10-14T12:12:12Z</a:updated>
<a:link rel="self" href="" />
<a:link href="/blog" />
<a:link rel="alternate" type="application/json" href="/blog;json" />

<a:entry xml:base="entries/1">
<a:id>tag:example.org,2007:/foo/entries/1</a:id>
<a:title type="text">Entry Number One</a:title>
<a:summary type="xhtml">
<div>
<p>This is the first entry. You can read it <a href="">here</a></p>
</div>
</a:summary>
<a:rights type="html">
<p>Copyright &copy; James M Snell</p>
</a:rights>
<a:updated>2007-10-14T12:12:12Z</a:updated>
<a:link href="" />
<a:link rel="alternate" type="application/json" href="1;json" />
<a:link rel="replies" type="application/atom+xml"
href="1;replies" thr:count="10" />
<a:content type="xhtml">
<div>
<p>This is the content of the first entry. It contains a picture.</p>
<img src="/images/foo.jpg" />
</div>
</a:content>
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/2" />
<a:category scheme="http://example.org/categories/" term="foo"
label="test" xml:lang="en-US" />
<a:category scheme="http://example.org/categories/" term="bar"
label="essai" xml:lang="fr" />
<foo:a><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
</a:entry>

<a:entry xml:base="entries/2" xml:lang="fr">
<a:id>tag:example.org,2007:/foo/entries/2</a:id>
<a:title type="text">La premiè
re entr
ée</a:title>
<a:summary type="xhtml">
<div>
<p>Il s'agit de la premiè
re entr
ée. Vous pouvez lire
<a href="">est ici</a></p>
</div>
</a:summary>
<a:rights type="html">
<p>Copyright &copy; James M Snell</p>
</a:rights>
<a:updated>2007-10-14T12:12:11Z</a:updated>
<a:link href="" />
<a:link rel="alternate" type="application/json" href="2;json" />
<a:link rel="replies" type="application/atom+xml"
href="2;replies" thr:count="10" />
<a:content type="xhtml">
<div>
<p>Ceci est le contenu de la premiè
re entr
ée. Il contient une image.</p>
<img src="/images/foo.jpg" />
</div>
</a:content>
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/1" />
<a:category scheme="http://example.org/categories/" term="foo"
label="test" xml:lang="en-US" />
<a:category scheme="http://example.org/categories/" term="bar"
label="essai" xml:lang="fr" />
<foo:a><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
</a:entry>
</a:feed>

여기에서 설명한 Atom-JSON 직렬화는 가독성 있고 유용한 결과를 제공하고, 중요한 정황 데이터의 손실을 피한다.


Listing 31. Listing 30의 전체 Atom 피드 문서의 JSON 직렬화 .
                
{
"lang":"en-US",
"dir":"ltr",
"id":"tag:example.org,2007:/foo",
"title":"Example Feed",
"subtitle":{
"attributes":{
"type":"html"
},
"children":[{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
} ] },
"rights":{
"attributes":{ "type":"xhtml" },
"children":[{
"name":"p",
"attributes":{ },
"children":["Copyright \u00a9 James M Snell" ]
} ]},
"updated":"2007-10-14T12:12:12.000Z",
"authors":[{
"name":"James M Snell",
"email":"jasnell@example.org",
"uri":"http://example.org/~jasnell"
} ],
"links":[
{
"href":"http://example.org/foo",
"rel":"self"
},
{
"href":"http://example.org/blog"
},
{
"href":"http://example.org/blog;json",
"rel":"alternate",
"type":"application/json"
} ],
"entries":[...],
"attributes":{
"xml:lang":"en-US",
"xml:base":"http://example.org/foo"
}
}




위로


Abdera JSON Writer 사용하기

여 기에 설명된 기술은 Apache Abdera 프로젝트의 일부로서 구현되었다. Listing 32의 코드는 Abdera JSON Writer의 사용법을 나타낸다. Atom-JSON 변환을 실험해 보고 싶다면, Abdera wiki를 방문하여 최신 개발 이미지를 다운로드 하는 방법을 참조하라.


Listing 32. Apache Abdera JSON Writer 사용하기
                
Abdera abdera = new Abdera();
Entry entry = abdera.newEntry();

entry.setId("http://example.org");
entry.setTitle("Testing the JSON Writer");
entry.setUpdated(new Date());
entry.addLink("http://www.example.org");
entry.addAuthor("James Snell");
entry.setSummary("This is a test of the JSON Writer");

entry.writeTo("json", System.out);




위로


결론

한 포맷에서 또 다른 포맷으로 데이터를 변환하는 것은 늘 어려운 일이었다. Atom 같은 데이터 포맷을 사용하여 JSON 같이 단순하고 기본적인 포맷으로 직렬화 하는 것은 큰 문제가 될 수 있다. 표준화 된 변형을 만들어내려는 노력이 진행되는 동안, 애플리케이션 개발자들은 품질 면에서 매우 광범위한 호환성 없는 직렬화를 다룰 준비를 해야 한다. 이 글에서 설명한 기술은 여러 가능한 방법들 중 일부일 뿐이다.



참고자료

교육

제품 및 기술 얻기

토론


필자소개

James Snell

James M. Snell은 IBM WebAhead 그룹의 소프트웨어 엔지니어로서, IBM에서 사용할 수 있는 핵심적인 기술들을 개발 및 적용하고 있다. Atom Syndication Format과 Atom Publishing Protocol을 정의하는 일에 참여하고 있으며, 아홉 개의 다른 Atom Publishing Protocol 서버를 구현했다.

[본문링크] Atom 문서를 JSON으로 변환하기 (한글)
[1]
코멘트(이글의 트랙백 주소:/cafe/tb_receive.php?no=7077
작성자
비밀번호

 

SSISOCommunity

[이전]

Copyright byCopyright ⓒ2005, SSISO Community All Rights Reserved.