JSON 문자열과 EGL 변수 간 대응

이 주제에서는 JSON(JavaScript Object Notation) 문자열에 해당하는 EGL 레코드에 대해 설명합니다. 기타 주제에서는 써드파티 REST 서비스에 액세스하는 데 필요하듯이 Rich UI 개발자가 JSON 데이터와 변수 간 변환을 수행하는 데 사용하는 함수(serviceLib.convertFromJSON(), serviceLib.convertToJSON())에 대해 설명합니다. 각 함수에서 실패가 발생하면 RuntimeException이 발생합니다.

JSON 및 EGL 레코드

다음과 같이 JSON 문자열에 액세스하는 경우 사용할 레코드를 정의할 수 있습니다.
{ "EmpNo":10,"LastName":"Smith" }  
JSON 문자열의 중괄호 내에서 각 ID - 값 쌍(예: "Empno":10)은 JSON 필드의 이름과 값입니다. JSON 문자열과 일치하는 레코드 파트를 작성하려면 다음 예제에 표시된 것처럼 레코드 파트의 각 필드 이름이 JSON 문자열의 각 해당 필드 이름과 문자와 대소문자가 정확히 일치하는지 확인하십시오.
Record MyRecordPart
   EmpNo INT;
   LastName STRING;
end

BLOB 또는 CLOB 이외의 모든 기본 유형을 사용할 수 있습니다. 또한 EGL 레코드 필드는 지원되는 기본 유형 중 하나를 기반으로 하는 DataItem 파트가 기반인 경우 올바릅니다.

EGL 특성 JSONName을 사용하면 필드 이름이 EGL 예약어이거나 EGL에서 올바르지 않은 JSON 문자열에 대한 작업을 수행할 수 있습니다. 다음은 JSON 문자열 예의 변형입니다.
{ "Emp-No":10,"LastName":"Smith" }  
이 경우 문제점은 하이픈을 포함하는 EGL 레코드 필드 이름을 작성할 수 없는 점입니다. 그러나 다음에 표시된 것처럼 JSONName 특성을 사용하여 레코드 파트에서 JSON 필드 이름을 유지할 수 있습니다.
Record MyRecordPart
   EmpNo INT; {JSONName = "Emp-No"}
   LastName STRING;
end

(레코드 파트를 기반으로 하는 레코드를 선언하는 경우 JSONName의 값을 대체할 수 없습니다.)

여러 상황에서 JSON 문자열에 액세스하기 위해 사용하는 레코드에는 레코드가 포함되어 있습니다. 그러나 레코드를 사용 중이고 serviceLib.convertFromJSON() 또는 serviceLib.convertToJSON()을 호출하는 경우 필요한 모든 레코드 파트의 최상위(가장 포괄적) 레코드 파트를 기반으로 하는 단일 레코드만 참조할 수 있습니다. 예를 들면, 1970년 1월 1일 이후의 시간(초)을 계산하는 getTime 서비스에서 다음 JSON 문자열이 리턴될 수 있습니다.
{"Result":{"aTimestamp":1191871152}}

일반 규칙은 JSON 문자열에서 중괄호로 묶인 각 절이 EGL 레코드에 해당하는 런타임 JSON 오브젝트의 컨텐츠라는 점입니다.

현재 예제에서 두 개의 레코드 파트를 정의해야 합니다. serviceLib.convertFromJSON() 또는 serviceLib.convertToJSON()에서 사용할 레코드는 Result 필드가 있는 다음 파트를 기반으로 합니다.
Record MyTopPart
   Result MyTimestampPart;
end
JSON 문자열의 구조가 주어지면 다음 레코드 파트에 aTimestamp 필드가 있습니다.
Record MyTimestampPart
   aTimestamp BIGINT;
end

표시된 것처럼 각 JSON ID(뒤에 콜론이 표시됨)를 사용하려면 레코드에 필드가 있어야 합니다. JSON 필드 이름이 EGL 예약어(예: "TimeStamp")인 경우에는 레코드가 아니라 사전을 사용하여 serviceLib.convertFromJSON() 또는 serviceLib.convertToJSON()에 액세스해야 합니다. 이 주제에서 나중에 이 변형을 보여줍니다.

다음은 JSON에 대해 자세히 설명하고 있는 http://json.org/ 웹 사이트에서 가져온 다른 예제(가독성을 위해 재형식화함)입니다.
{"Menu": 
  { "id": "file", "value": "File", "popup": 
     {"Menuitem": 
       [
         {"value": "New", "onClick": "CreateNewDoc()"},
         {"value": "Open", "onClick": "OpenDoc()"},
         {"value": "Close", "onClick": "CloseDoc()"}
       ]   
     }
  }
}

(이 문서에서 해당 예제와 기타 예제는 http://json.org/example.html에 있습니다.)

최상위(가장 포괄적) 레코드 파트는 Menu 필드를 포함합니다.
Record MyTopPart
   Menu MyMenuPart;
end
기타 레코드 파트를 빌드하기 위해 JSON 문자열의 중괄호 안에 있는 각 절을 검토합니다. 다음 레코드 파트(MyMenuPart)는 id, value, popup 필드를 포함합니다.
Record MyMenuPart
   id STRING; 
   value STRING;
   popup MyPopupPart;
end
다음 레코드 파트는 MenuItem 배열을 포함합니다.
Record MyPopupPart
   MenuItem MyElementPart[];
end
마지막 레코드 파트는 value 필드와 onClick 필드를 포함합니다.
Record MyElementPart
   value STRING; 
   onClick STRING;
end

JSON 문자열에 액세스할 때 레코드를 사용하는 방법을 자세히 탐색하려면 Rich UI 샘플 geocode.records를 참조하십시오.

JSON 및 EGL 사전

EGL 사전에는 다음 변수 선언과 같이 모든 유형의 키와 값으로 구성된 항목의 세트가 있습니다.
myRef Dictionary 
{ 
   ID = 5,
   lastName = "Twain",
   firstName = "Mark"
};

EGL 도움말 시스템의 "사전 파트"와 관련 주제에 설명된 대로 사전과 상호작용합니다.

1970년 1월 1일 이후의 시간(초)을 계산하는 getTime 서비스에서 다음 JSON 문자열이 리턴될 수 있습니다.
{"Result":{"aTimestamp":1191871152}}
JSON 문자열(가장 왼쪽의 중괄호에서 가장 오른쪽의 중괄호까지)을 세부사항 없이 선언되는 myTime 사전으로 변환할 수 있습니다.
myTime Dictionary;

일반 규칙은 JSON 문자열의 중괄호 안에 있는 각 절이 EGL 사전에 해당한다는 점입니다. 예제 JSON 문자열과 관련하여 serviceLib.convertFromJSON() 함수는 첫 번째 콜론(:)의 왼쪽에 있는 기호를 사전 항목의 키로 처리합니다. 키는 Result이고 대소문자를 구분합니다. 여기서(모든 경우에서와 마찬가지로) 콜론 오른쪽의 컨텐츠는 콜론의 왼쪽에 이름이 있는 키와 연관된 값입니다.

임베디드 중괄호는 Result의 값이 익명의 사전임을 표시합니다. 앞의 경우처럼 해당 중괄호 안의 콜론은 키(aTimestamp)와 값(1191871152)을 구분합니다. 간단히 말하면 serviceLib.convertFromJSON() 함수의 출력을 다음과 같이 생각할 수 있습니다.
myTime Dictionary 
{ 
   Result = new Dictionary{ aTimestamp = 1191871152 }
};   
점으로 구분된 구문을 사용하여 aTimestamp의 컨텐츠에 액세스할 수 있습니다.
numberOfSeconds BIGINT = myTime.Result.aTimestamp;
때로는 점으로 구분된 구문이 올바르지 않습니다. 예를 들어, Yahoo getTime 서비스가 EGL 예약어 Timestamp를 포함하는 다음 컨텐츠를 리턴했습니다.
{"Result":{"Timestamp":1191871152}}
키가 EGL 예약어인 값에 액세스하려면 대괄호 구문을 사용해야 합니다. 다음 EGL 코드는 Yahoo getTime 서비스에서 리턴된 데이터에 올바릅니다.
numberOfSeconds BIGINT = myTime.Result["Timestamp"];
다음은 다시 http://json.org/의 Menu 예제입니다.
{"Menu": 
  { "id": "file", "value": "File", "popup": 
     {"Menuitem": 
       [
         {"value": "New", "onClick": "CreateNewDoc()"},
         {"value": "Open", "onClick": "OpenDoc()"},
         {"value": "Close", "onClick": "CloseDoc()"}
       ]   
     }
  }
}

이 예제에서 사전에는 키의 이름이 Menu로 지정된 하나의 항목이 있습니다. 문자열 "id"와 그 뒤의 모든 문자열을 임베드하는 중괄호로 표시된 대로 해당 키와 연관된 값은 익명 사전입니다. 이 익명 사전에는 id, value, popup 키와 해당 키의 값이 포함되어 있습니다. popup 키가 소개하는 유형의 복잡도를 경험하지 않을 수 있지만 문제점은 해결 가능합니다. JSON 문자열 예에서 관계를 볼 수 있습니다.

고려할 질문은 다음과 같습니다. serviceLib.convertFromJSON() 함수가 이전 JSON 문자열을 myMenu 사전에 복사했다고 가정했을 때 문자열 "OpenDoc()"에 액세스하는 데 필요한 명령문은 무엇입니까?

답은 다음과 같습니다.
myString STRING = myMenu.Menu.popup.MenuItem[2].onClick;
다음 EGL 사전은 현재 예제를 반영합니다.
myMenu Dictionary
{  Menu = new Dictionary
   { id = "file",
     value = "File",
     popup = new Dictionary 
     { MenuItem = new Dictionary[]
       { new dictionary {value = "New", onClick = "CreateNewDoc()" },
         new dictionary {value = "Open", onClick = "OpenDoc()" },
         new dictionary {value = "Close", onClick = "CloseDoc()"}
       } 
     } 
   }
};     
serviceLib.convertToJSON() 함수 관련 작업을 수행하려면 앞의 예제에 표시된 것처럼 구조화된 사전을 작성하여 시작하십시오. 다음 두 개의 규칙이 적용됩니다.
  • 사전 계층 구조에 있는 각 사전은 JSON 문자열에서 중괄호 안에 있는 절에 해당합니다.
  • 각 키에는 기본 값, 사전, 레코드 또는 사전이나 레코드의 배열이 지정됩니다.

JSON 문자열에 액세스할 때 사전 레코드를 사용하는 방법을 자세히 탐색하려면 Rich UI 샘플 geocode.dictionaries를 참조하십시오.

JSON 및 레코드와 사전

다음 경우에 레코드와 사전을 함께 사용할 수 있습니다.
  • 레코드를 사용하여 serviceLib.convertFromJSON()을 호출하려고 준비하는 경우
  • 레코드 또는 사전을 사용하여 serviceLib.convertToJSON()을 호출하려고 준비하는 경우
레코드에 사전을 포함하여 다음 JSON 문자열에 액세스할 수 있습니다.
{"Result":{"Timestamp":1191871152}}
다음 파트를 정의할 수 있습니다.
Record ResultRecordPart
   Result Dictionary;
end
사용자 코드가 다음과 같이 시간소인 값에 액세스할 수 있습니다.
   myResult ResultRecordPart;
   milliseconds BIGINT;
		serviceLib.convertFromJSON(resp.body, myResult);
		milliseconds = myResult.Result["Timestamp"] as BIGINT;
일반 규칙은 수신 JSON 절을 사전과 연관시키는 경우 사전 구문을 사용하는 경우에만 절 내의 데이터에 액세스할 수 있다는 점입니다. 복잡한 예는 다음과 같습니다.
{"Menu": 
  { "id": "file", "value": "File", "popup": 
     {"Menuitem": 
       [
         {"value": "New", "onClick": "CreateNewDoc()"},
         {"value": "Open", "onClick": "OpenDoc()"},
         {"value": "Close", "onClick": "CloseDoc()"}
       ]   
     }
  }
}
컨텐츠에 액세스할 준비를 하기 위해 다음 파트를 정의할 수 있습니다.
Record MyTopPart
   Menu MyMenuPart;
end
Record MyMenuPart
   id STRING; 
   value STRING;
   popup Dictionary; 
end
다음 EGL 사전은 popup 구조를 반영합니다.
   popup Dictionary 
   { MenuItem = new Dictionary[]
      { new Dictionary {value = "New", onClick = "CreateNewDoc()" },
        new Dictionary {value = "Open", onClick = "OpenDoc()" },
        new Dictionary {value = "Close", onClick = "CloseDoc()"}
      } 
   } 

(설명을 위해 해당 사전을 표시합니다. Dictionary의 하위 구조는 serviceLib.convertToJSON()을 호출할 경우 유용하지만 serviceLib.convertFromJSON()을 호출할 경우에는 사용되지 않습니다.)

다음 코드는 "OpenDoc()" 문자열에 액세스합니다.
   myTop MyTopPart;
   itemString STRING;
   serviceLib.convertFromJSON(resp.body, myTop);
   itemString = myTop.Menu.popup.MenuItem[2].onClick;