네트워크 인식 소프트웨어를 구축할 때 설계 과정에서 올바른 데이터 교환 형식을 선택해야 합니다. 특히 모바일 애플리케이션과 임베디드 애플리케이션을 설계할 때는 가볍고 효율적인 특성이 중요한 고려 사항이므로 더욱 신중하게 선택해야 합니다. 그러한 특성을 갖추고 있으면 사용 요구 사항 및 전력 사용을 줄일 수 있고, 잠재적으로 더 나은 성능을 발휘할 수 있으며, 작업 비용을 낮출 수 있으므로 중요합니다.

모 바일 애플리케이션에서 개발자는 일반적으로 자체 제작 데이터 교환 형식이나 XML(Extensible Markup Language)에 의존합니다. 자체 제작 데이터 교환 형식의 장점은 성능 및/또는 컴퓨팅 리소스를 최대화할 수 있도록 특정한 상황에 맞게 조정할 수 있다는 점입니다. XML(Extensible Markup Language)의 장점은 HTTP를 통해 사용하는 경우 사실상 데이터 교환의 표준이라는 점입니다. 또한 XML에서 사용되는 텍스트 기반의 사람이 읽을 수 있는 표시 방법으로 인해 더욱 쉽게 디버깅할 수 있습니다.

이러한 두 가지 방법은 단점도 있습니다. 자체 제작 데이터 교환 형식은 소유 자산의 특성이 있고, 비표준이며, 상호 운용성이 떨어질 가능성이 있는 반면, XML의 경우 데이터 표시용으로는 너무 무겁고 장황하다고 생각될 수 있습니다. 모바일 애플리케이션과 임베디드 애플리케이션의 경우에는 특히 그렇습니다.

JSON과 XML의 비교
JSON 과 XML의 비교는 독자에게 맡기겠습니다. XML만 사용하는 사람은 JSON이 불필요한 발명품이 아니냐고 질문합니다. 웹을 검색하면 이러한 주제에 관한 토론을 많이 찾을 수 있습니다. 마지막으로 JSON과 XML의 비교는 런타임 환경, 구문 분석기 가용성, 통합 및 애플리케이션 요구 사항을 근거로 답해야 합니다.
 

이 경우 대안으로 고려할 수 있는 것은 경량 데이터 교환 형식인 JSON(JavaScript Object Notation)입니다. 이 문서에서는 Java 플랫폼 Micro Edition(Java ME)에서 데이터 교환에 사용할 수 있는 JSON을 소개합니다.

JSON은 JavaScript(ECMAScript) 스크립팅 언어의 일부로 정의됩니다. JSON은 JavaScript용으로 만들어졌기 때문에 브라우저 기반 애플리케이션에 적합합니다. 그러나 JSON은 JavaScript에서만 사용할 수 있도록 제한되어 있지 않고 경량이라서 일반적으로 모바일 애플리케이션과 임베디드 애플리케이션용으로 매우 좋습니다.

JSON은 두 가지 기본 데이터 구조를 바탕으로 하는 매우 간단한 구문을 사용합니다.

  • 이름/값 쌍 모음 및
  • 값 순서 목록

JSON 은 텍스트 기반이라 사람이 해독할 수 있으므로 디버깅하기에 좋습니다. JSON은 모든 기본 데이터 형식을 표시할 수 있도록 지원하고 자바 기본 형식의 앞뒤로 구문 분석하는 방법을 제공합니다. 다음 표에서는 JSON 구문 요소를 간단하게 설명합니다.

다음의 JSON 텍스트 코드 단편은 JSON-Time에 대한 요청과 응답을 보여 줍니다. JSON-Time은 지정한 시간대의 현재 시간을 반환하는 유용한 웹 서비스입니다. 다음 예는 현재 미국 시간에 대한 요청과 응답입니다.

목록 1 - JSON-Time HTTP 요청 및 JSON 텍스트 응답

Request:

http://json-time.appspot.com/time.json?tz=US/Central

Response:

{
"tz": "US\/Central",
"hour": 15,
"datetime": "Tue, 05 Aug 2008 15:02:27 -0500",
"second": 27,
"error": false,
"minute": 2
}
 

응답은 간단한 JSON 텍스트 구조인 명명되지 않은 개체로서 제대로 이스케이프된 값, 문자열, 숫자, 부울을 포함합니다.

참고) 바이너리 데이터란 무엇입니까?
JSON 은 텍스트 기반 데이터 표시 형식입니다. 모든 텍스트 기반 형식과 마찬가지로 바이너리 데이터는 텍스트로 인코딩해야 합니다. 한 가지 방법은 바이너리 데이터를 기본 64 인코딩으로 변환하는 것이고, 또 한 가지 방법은 바이너리 데이터를 16진수 값 같은 다른 텍스트 인코딩 형식으로 변환하는 것입니다(예: [\uDEAD, \uBEEF,...]).

JSON은 모든 기본 숫자 및 문자열 데이터 형식을 지원합니다. 숫자는 정수, 분수, 지수이지만, 부동 소수점/실수 데이터 형식은 CLDC 1.0에서 지원되지 않습니다. 문자열은 모든 유니코드 문자입니다.

다음 문자는 백슬래시 문자를 사용하여 제대로 이스케이프해야 합니다.

  • 인용 부호(\")
  • 백슬래시(\\)
  • 슬래시(\/)
  • 백스페이스(\b)
  • 폼 피드(\f)
  • 줄바꿈 문자(\n)
  • 캐리지 리턴(\r)
  • 탭(\t)
  • 16진수 숫자(\u4-hex-digits)

JSON 구문에 대한 자세한 내용은 JSON.org를 참조하십시오.

모바일 및 임베디드 애플리케이션 개발자 프로젝트의 일환으로 Sun Microsystems는 ME Java API용 개방형 소스(Java.net) 프로젝트 버전의 JSON을 제공합니다. 이 소스 코드는 CLDC 1.0과 1.1(부동 소숫점 지원)에서 각각 조건부 컴파일을 수행하는 방법을 비교한 적절한 지침과 함께 제공됩니다. JSON ME 소스 코드는 JSON.org에서도 사용할 수 있지만 조건별 지침은 없습니다.

예상대로 JSON ME는 전체 JSON Java API의 일부입니다. 다음 표에서는 JSON Java API에 대해 간단히 설명합니다.

표 2 - JSON ME Java API
패키지 이름
클래스
org.json.me
  • JSONArray는 값의 순서입니다.
  • JSONException은 탐지된 오류입니다.
  • JSONObject는 이름/값 쌍이 순서대로 나열된 모음입니다.
  • JSONString은 JSON 직렬화의 인터페이스입니다.
  • JSONStringer는 JSON 구문을 생성하기 위한 JSONWriter의 하위 클래스입니다.
  • JSONTokenerJSONObjectJSONArray에서 사용하는 구문 분석 유틸리티 클래스입니다.
  • JSONWriter는 JSON 구문을 생성하는 편리한 클래스입니다.
  • StringWriterStringWriterStringBuffer 기반 구현입니다. 이 클래스는 표준 JSON Java API의 일부가 아니라 Sun Microsystems 헬퍼 클래스입니다.
org.json.me.util
  • XML은 XML에서 JSON을 생성하는 헬퍼 클래스입니다.
  • XMLTokener는 XML 구문 분석을 지원하기 위해 JSONTokener를 확장합니다.
 

JSON과 JSON ME는 사용하는 일부 데이터 형식(예를 들어 JSON ME는 VectorHashtable 사용), 그리고 부동 소숫점 지원(CLDC 1.1)과 관련된 조건부 컴파일을 위한 컴파일러 명령 등 내부적으로 차이가 있습니다. JSON ME JAR 파일은 25KB 정도 됩니다.

JSON Java API는 JSONWriterJSONStringer 등 편리한 클래스 몇 가지를 제공하여 JSON 텍스트를 생성합니다. 저는 개인적으로 코어 JSONObject를 직접 JSONArray와 함께 사용하는 방법을 선호합니다. 이 경우 필요한 구문 분석 기능은 제공합니다. 앞서 언급한 이러한 코어 클래스를 사용하여 간단한 DataTypes 예제 클래스를 JSON에서 직렬화하거나 직렬화를 해제하여 JSON으로 되돌리는 간단한 예를 몇 가지 들어 보겠습니다. 다음 코드 단편은 우리가 예제로 사용할 JSON 텍스트를 보여 줍니다.

목록 2 - JSON 텍스트 예제
{
"datatypes": {
"aString":"C. Enrique Ortiz",
"anArray":["tech","mobile","web", "apps"],
"aInteger": 15569,
"aLong": 1234567890,
"aBoolean": true,
}
}
 

매우 간단해 보이지요? JSON을 사용하면 개체를 개체 안에 중첩하고 XML에서 정의할 수 있는 모든 데이터 구조를 정의할 수 있습니다.


JSONObject가 앞으로 사용할 코어 JSON Java 클래스입니다. 이 클래스는 다음과 같은 작업을 수행하는 여러 가지 헬퍼 메소드를 제공합니다.

  • 키 아래에 값 누적(accumulate)
  • 키 아래의 어레이에 값 추가(append)
  • 실수(double)에서 문자열 생성
  • Java Object, boolean, double, int, JSONArray, JSONObject, long을 가져오고(get), 값을 같은 데이터 형식으로 입력하는(put) 반대 메소드
  • JSONObject 내에서 필드 이름 가져오기(get)
  • 특정 키와 연관된 값 가져오기(get)
  • JSONObject 내에 특정 키가 있는지 검색
  • 키와 연관된 값이 null인지 또는 값이 없는지 확인
  • JSONObject의 키 열거(Enumeration)
  • JSONObject에 저장된 키 수 가져오기
  • JSONObject의 요소 이름이 포함된 JSONArray 가져오기
  • 숫자에서 문자열 생성
  • 백슬래시가 적절한 위치에 삽입되어 있고 인용 부호 내에 포함된 상태의 문자열 생성
  • 이름 및 해당 값이 있으면 제거
  • JSONObject의 키 열거(Enumeration)
  • JSONObject의 구성원 값이 포함된 JSONArray 생성
  • JSONObject의 JSON 텍스트 생성

예제 DataTypes 클래스
다음 코드 단편은 JSON ME에서 지원하는 데이터 형식이 포함된 DataTypes 예제 Java 클래스를 정의합니다. 이 클래스는 JSON으로/에서 직렬화하는 방법을 보여 주는 데 사용할 클래스입니다. 다시 한 번 강조하지만, CLDC 1.0에서는 고정 소숫점/실수를 지원하지 않습니다.

목록 3 - DataTypes 예제 클래스
/**
* A data types class to use as example
*/
class DataTypes {
public String aString; // a string
public String[] anArray; // an array
public int anInteger; // an integer
//public double aDouble; // double not supported on CLDC 1.0
public long aLong; // a long
public boolean aBoolean; // a boolean

/**
* An example multi-data type Class
*/
public DataTypes(
String aString,
String[] anArray,
int anInteger,
//double aDouble, // Not supported on CLDC 1.0
long aLong,
boolean aBoolean) {
this.aString = aString;
this.anArray = anArray;
this.anInteger = anInteger;
//this.aDouble = aDouble; // Not supported on CLDC 1.0
this.aLong = aLong;
this.aBoolean = aBoolean;
}

:
:

}
 

지원되는 데이터 형식은 String, int, long, boolean 및 앞서 말한 이러한 기본 데이터 형식의 어레이입니다.

JSON으로 직렬화: JSON 텍스트 생성
이제 DataTypes 클래스 인스턴스의 JSON 텍스트 표시를 만들어 보겠습니다. JSON Java API는 Java에서 JSON과 유사한 구문을 사용할 수 있는 헬퍼 클래스(JSONWriterJSONStringer)를 제공하지만 다음 예제에서는 간단하고 효과적인 API인 JSONOjbect와 JSONArray를 직접 사용합니다. 또한 이 방법에서 사용되는 코드는 XML을 생성하는 코드에 쉽게 매핑할 수 있습니다. 아래의 코드 단편은 toJSON() 헬퍼 직렬화 메소드를 보여 줍니다.

목록 4 - JSON 텍스트 생성
/**
* Serializes this DataTypes instance
*
* @return the serialized DataTypes as JSON text
*/
public String toJSON() {
// Define an external an a nexted JSONObjects
JSONObject outer = new JSONObject();
JSONObject inner = new JSONObject();
// Now generate the JSON output
try {
outer.put("datatypes", inner); // the outer object name
inner.put("aString", aString); // a name/value pair
JSONArray ja = new JSONArray();
for (int i=0; i<anArray.length; i++) {
ja.put(anArray[i]);
}
inner.put("anArray", ja); a name/value pair
inner.put("anInteger", anInteger); a name/value pair
//inner.put("aDouble", aDouble); // Not supported on CLDC 1.0
inner.put("aLong", aLong); a name/value pair
inner.put("aBoolean", aBoolean); a name/value pair
} catch (JSONException ex) {
// ...process exception
}
return outer.toString(); // return the JSON text
}
 

참고: 하드 코딩된 텍스트 문자를 사용하는 것은 좋은 방법이 아니지만 강조하여 보여드리기 위해 예제 코드 단편에서 사용한 것입니다.

JSON 직렬화 해제: JSON 텍스트에서 클래스 초기화
다음 코드 단편은 입력한 JSON 텍스트 문자열의 직렬화를 해제하고 DataType 클래스의 인스턴스를 초기화하는 fromJSON() 헬퍼 메소드를 보여 줍니다.

목록 5 - 입력 JSON 텍스트 문자열에서 개체 초기화
/**
* Initializes this instance of UserInfo and de-serializes the
* input JSON string
*
* @param ji is the input JSON string
*/
public void fromJSON(String ji) {
// First, clear the object.
aString = null;
anArray = null;
anInteger = 0;
//aDouble = 0.0; // Double not supported on CLDC 1.0
aLong = 0;
aBoolean = false;

// Now initialize from JSON text.
try {
JSONObject outer = new JSONObject(ji); // the outer objet
if (outer != null) {
// Get the inner object and parse out the data
JSONObject inner = outer.getJSONObject("datatypes");
if (inner != null) {
// Parse the name/value pairs
aString = inner.getString("aString");
JSONArray ja = inner.getJSONArray("anArray");
if (ja != null) {
anArray = new String[ja.length()];
for (int i=0; i<ja.length(); i++) {
anArray[i] = (String) ja.get(i);
}
}
anInteger = inner.getInt("anInteger");
//aDouble = inner.getDouble("aDouble");
aLong = inner.getLong("aLong");
aBoolean = inner.getBoolean("aBoolean");
}
}
} catch(Exception e) {
// ...process exception
}
}
 

직렬화 메소드 사용
다음 코드 단편은 위의 toJSON()fromJSON() JSON 직렬화 메소드를 사용하는 방법을 보여 줍니다.

목록 6 - JSON 직렬화 메소드 사용
// Create an initialize instance of DataTypes
DataTypes dt = new DataTypes(
"C. Enrique Ortiz", // a String
new String[] {"tech","mobile","web", "apps"}, // an Array
15569, // an int
//0.0, // a double, not supported on CLDC 1.0
1234567890, // a long
true); // a boolean

// Covert object to JSON
String j = dt.toJSON();
System.out.println("*** toJSON: " + j);

// Initialize object from JSON
System.out.println("*** fromJSON:");
dt.fromJSON(j);

// Dump to console to see if it worked
dt.dump();
 

다음은 디버깅을 위해 앞의 코드에 사용되는 dump() 헬퍼 메소드입니다.

목록 7 - 디버깅을 위한 dump() 헬퍼 메소드
/**
* Dump DataTypes for debugging
*/
public void dump() {
System.out.println(" aString: " + aString);
if (anArray != null) {
for (int i =0; i<anArray.length; i++) {
System.out.println(" tag [" + i + "]: " + anArray[i]);
}
}
System.out.println(" anInteger: " + anInteger);
//System.out.println(" aDouble: " + aDouble);
System.out.println(" aLong: " + aLong);
System.out.println(" aBoolean: " + aBoolean);
}
 

이 문서에서는 XML에 대한 대안으로 ME용 JSON을 소개했습니다. JSON의 특징은 모바일 애플리케이션 및 임베디드 애플리케이션에 적합한 경량이라는 점입니다. Sun Microsystems에서 개발한 ME Java API용 JSON을 사용하면 JSON 텍스트를 쉽게 구문 분석할 수 있습니다. API는 작으면서도 애플리케이션 내에서 데이터를 교환하는 데 필요한 모든 기능을 제공합니다.

 

C. Enrique Ortiz는 오랫동안 모바일 기술자 겸 블로거로 활동했습니다. 모바일 기술에 열광하며 실제로 모바일 기술을 개발하는 전문가로, 다년 간 전반적인 모바일 컴퓨팅 관련 일을 하고 있습니다.

이 글의 영문 원본은
Using JavaScript Object Notation (JSON) in Java ME for Data Interchange
에서 보실 수 있습니다.

"Java ME" 카테고리의 다른 글

2008/10/13 15:31 2008/10/13 15:31

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/670

댓글을 달아 주세요

[로그인][오픈아이디란?]

◀ Prev 1  ... 22 23 24 25 26 27 28 29 30  ... 641  Next ▶