레이블이 json인 게시물을 표시합니다. 모든 게시물 표시
레이블이 json인 게시물을 표시합니다. 모든 게시물 표시

2014년 5월 1일 목요일

Regarding Tizen native REST client app development (HTTP, JSON parser, Event-driven thread)

아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
--------------------------------------------------------------------------- Tizen native app으로 REST client app을 개발하고자
관련된 tutorial 링크 및 참고 사항들을 대충 정리 함...

- HTTP request/response 처리
- JSON parsing
- HTTP response 처리를 위한 Event-driven thread 사용

[HTTP transaction concept]

https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/net/http_transaction.htm

REST client app을 만드니... 기본적인 HTTP transaction에 대해서는 이해가 필요하겠지..

 . HTTP transaction 에 대한 내용들
http://www.pearsonhighered.com/assets/hip/us/hip_us_pearsonhighered/samplechapter/0672324547.pdf



http://www.w3.org/2002/Talks/www2002-p3p/all.htm

 . Chunked transfer
  : 간단히 말하면 일반적인 http streaming transfer는 content를 response로 한번에 보내지만 chunked transfer는 content를 임의의 크기로 쪼개서 보냄. 이런 경우는 server측의 performance의 제약이나 전달되는 content가 실시간 생산되는 content의 경우(크기를 예측할 수 없음) 이런 방법을 사용.
  : Tizen HTTP transfer default mode는 Non chunked transfer mode 이지만 일반적인 server에서는 chunked transfer 지원.
  : http://en.wikipedia.org/wiki/Chunked_transfer_encoding

[HTTP request/response]


[HttpClient Sample Overview]
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/sample_descriptions/httpclient.htm



HTTP request를 전송하고 response의 body bytes 수를 표시하는 sample app.
tizen.org 를 대상으로 HTTPS request를 실행하므로 외부 network으로 연결에 문제가 없는 지 확인 필요. (proxy 같은)

[HTTP Client]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/tutorials/net_tutorial/task_httpclient.htm

* HTTP request 시 http transaction을 asynchronous 하게 처리하기 위해 아래 IHttpTransactionEventListener 등록이 필요

Tizen::Net::Http::IHttpTransactionEventListener
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Net_1_1Http_1_1IHttpTransactionEventListener.html

  • OnTransactionAborted
  • OnTransactionCertVerificationRequestedN
  • OnTransactionCertVerificationRequiredN
  • OnTransactionCompleted
  • OnTransactionHeaderCompleted
  • OnTransactionReadyToRead
  • OnTransactionReadyToWrite


HTTP-GET 시나리오에서
no chunked transfer에서는 response header 전달 이후 전체 body가 전송되므로 다음과 같은 이벤트가 발생할 것이고

Client   event                                                                         Server
                                                 GET request >
 HeaderCompleted event        < response header
 Completed event                   < response body

chunked transfer에서는 response header 전달 이후 body가 나눠서 오므로 다음과 같은 이벤트가 발생할 것이다.

Client    event                                                                        Server
                                                 GET request >
 HeaderCompleted event        < response header
 ReadyToRead event               < response body
 ReadyToRead event               < response body
 ReadyToRead event               < response body
 Completed event                   < response body

HTTP-POST 시나리오는 아마도 이렇지 않을까? (해보지는 않음.)

Client     event                                                                       Server
                                          POST request header >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
 Completed event                   < response body


[주의 및 참고]

* HTTP transfer를 app에서 사용 하려면 http privilege가 필요
  . manifest.xml > privileges > http://tizen.org/privilege/http

* HttpSession의 copy constructor가 private 인 관계로 reference를 사용할 수 없음

* 일반적인 얘기겠지만 HttpSession의 instance를 http transaction 중 유지하지 않으면 listener 호출 중 crash 발생됨.

* Http request 시 특정 사용자 정보를 response callback에서 확인하려면 HttpTransaction의 SetUserObject()를 사용하라 HttpTransaction instance는 request, response시 모두 접근할 수 있음.
 : https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Net_1_1Http_1_1HttpTransaction.html#a8eff3be989218969838e76310cf99706


[HTTP programming guide]

나머지 항목들은 한번 보시라.

The most common uses of HTTP connectivity are the following:
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/net/http_connectivity.htm


[JSON]


Introduction to JSON on Tizen
https://developer.tizen.org/documentation/articles/introduction-json-on-tizen

JSON Parser App
https://developer.tizen.org/dev-guide/2.2.0/?topic=%2Forg.tizen.native.appprogramming%2Fhtml%2Ftutorials%2Fweb_tutorial%2Ftask_jsonparserapp.htm

이 예제에서는 JSON data를 parsing해서 key, value list를 제공해 주는 예제다.
단지 JSON data인 string을 parsing해서 탐색 가능한 data structure로 제공해 준다는 의미만 있을 뿐.. 그 이상의 편의는 제공하지 않는다.
사용자가 json response를 직접 parsing 해서 원하는 value를 가져오거나 utility 함수를 만들어서 key에 맞는 value를 가져오도록 해야 할듯.

   // Call JSON parser
   IJsonValue* pJson = JsonParser::ParseN(buf);

   __pJsonKeyList->RemoveAll(true);
   __pValueList->RemoveAll(true);
   TraverseFunction(pJson);


void
JsonForm::TraverseFunction(IJsonValue* pValue)
{   
   switch (pValue->GetType())
   {
      case JSON_TYPE_OBJECT:
      {
         JsonObject* pObject = reinterpret_cast< JsonObject* >(pValue);
         IMapEnumeratorT<const String*, IJsonValue*>* pMapEnum = pObject->GetMapEnumeratorN();

         while (pMapEnum->MoveNext() == E_SUCCESS)
         {

...
 case JSON_TYPE_STRING:
      {
         JsonString* pVal = reinterpret_cast< JsonString* >(pValue);
...
 case JSON_TYPE_ARRAY:
      {
         JsonArray* pJsonArray = static_cast< JsonArray* >(pValue);
         pJsonArray->GetCount();
         IEnumeratorT<IJsonValue*>* pEnum = pJsonArray->GetEnumeratorN();
         while (pEnum->MoveNext() == E_SUCCESS)
...
...

[Alternatives JSON parsers]

JsonCpp
: boost library 기반, library 생성을 위한 컴파일 필요
: http://jsoncpp.sourceforge.net/

cJSON
: simple, MIT license, 2013년이 최신 업데이트
: http://sourceforge.net/projects/cjson/

jsmn
: simple, MIT license, 아직 개발중으로 보임 2014년 최근까지 수정 내역 있음.
: https://bitbucket.org/zserge/jsmn/overview


다른 대안을 찾아 보니 위의 것들이 있었고 http://www.json.org/ 중간에 보면 각 언어에 맞는 json parser library들이 존재하니 알아서 취사 선택하면 될듯함.

간단하게 사용하고자 cJSON을 사용하였고 사실 Tizen에서 제공하는 JSON parser와 기능은 거의 동일하지만 c style로 api 사용 및 array 처리가 간단하다.
JsonCpp도 많이 사용하고 편리한 사용성의 api들을 제공하지만 boost library를 사용하므로 boost library의 cross compile이 필요하고 소스의 양도 좀 되서 그냥 패스함.


cJSON을 통해 parsing하면 cJSON* 이 리턴되고 이를 사용해서 key에 맞는 value들을 뽑아 내면 됨.

typedef struct cJSON {
struct cJSON *next,*prev;     /* next/prev allow you to walk array/object chains.
                                                      Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */

struct cJSON *child;             /* An array or object item will have a child pointer pointing to
                                                        a chain of the items in the array/object. */


int type; /* The type of the item, as above. */

char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */

char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;


일반적이 primitive value들은 list traversal 방법으로 확인하면 되며 array나 object들은 아래 함수를 사용해서 뽑아내면 된다.

/* Get Array size/item / object item. */
int          cJSON_GetArraySize(cJSON *array)
cJSON *cJSON_GetArrayItem(cJSON *array,int item)
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)


cJSON* element = null;
element = cJSON_GetObjectItem(item, "peoples");
if(null != element)
{
int size = cJSON_GetArraySize(element);
for(int i = 0 ; i < size ; i++)
{
cJSON* child_element = cJSON_GetArrayItem(element, i);
AppLog("peoples (%d) = %s - %s", i, child_element->string, child_element->valuestring);
...
}
element = null;
}

[Thread]

https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/base/thread.htm

Tizen에서는 아래와 같은 두가지(Main thread 제외)의 thread model들이 사용할 수 있고 각각의 특색은 다음과 같음.

[Event-driven Thread]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Runtime_1_1EventDrivenThread.html
: Event-driven threads run based on events and they execute in a loop until they receive an event notification to terminate. Event-driven threads allow using asynchronous calls.

[Worker Thread]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Runtime_1_1Thread.html
: Worker threads run linearly; they only execute the main body of the thread and exit. Asynchronous calls cannot be used, since the thread does not run an event-loop.




주기적인 HTTP request/response를 처리하고자 할 경우 Event-driven thread를 사용해야 함. 단순 http request/reponse를 처리할 때는 상관없으나 loop을 사용할 경우 worker thread에서는 바로 error가 발생하는 것으로 보인다. 실제 tizen platform에서 처리하는 방법은 알 수 없으나 주기적으로 반복해야 하는 상황에서는 event driven thread를 사용하는게 필요 함.

사용상의 별 특이점은 없음. 예제대로 만들면 잘 돌아감.. ㅎ

2014년 3월 11일 화요일

Unity 개발 시 REST api 호출 방법과 json library 관련 링크 정리

[REST API invoke in Unity]

REST API를 사용하기 위해서는 REST server로 접속, response 획득, response parsing이 필요하고 C#에서 REST API를 위한 library들이 많아서 입맛에 맞는 것을 찾아서 사용해도 될것 으로 보임.

REST API 호출 시 Response를 받아 처리하는 부분을 비동기적으로 처리해야 하는 부분이 있어 co-routine 방식을 사용해야 함 (이 부분은 더 상세하게 봐야 함.)

http://through-the-interface.typepad.com/through_the_interface/2012/04/calling-a-web-service-from-a-unity3d-scene.html
: Unity상에서 WWW class를 사용해서 web-service API를 사용하는 예제

public class ImportSpheres : MonoBehaviour
{
  // The radius of our outer sphere 
  const float radius = 0.8f;

  IEnumerator DownloadSpheres()
  {
    // Pull down the JSON from our web-service 
    WWW w = new WWW(
      "http://apollonian.cloudapp.net/api/spheres/" +
      radius.ToString() + "/7"
    );
    yield return w;

    print("Waiting for sphere definitions\n");

    // Add a wait to make sure we have the definitions 
    yield return new WaitForSeconds(1f); 
    print("Received sphere definitions\n");

    // Extract the spheres from our JSON results 
    ExtractSpheres(w.text);
  } 
  void Start ()
  {
    print("Started sphere import...\n"); 
    StartCoroutine(DownloadSpheres());
  } 
  void ExtractSpheres(string json)
  {
    // Create a JSON object from the text stream 
    JSONObject jo = new JSONObject(json);


http://answers.unity3d.com/questions/11021/how-can-i-send-and-receive-data-to-and-from-a-url.html
: C#, JavaScript에서 GET, POST 사용 예

The normal way of doing this would be to use Get or Post requests via the WWW class or the WWWForm class. If you're making a Get request with parameters added to the end of the url, you'd use code similar to this:
'GET' request In C#
In C# this is a little more complex because of the way that you have to write out coroutines in full. In this example, the initiation of the request is done in "Start". We then hand the WWW object to a coroutine called "WaitForRequest" which waits for the www request to complete.
  1. using UnityEngine;
  2. public class GetURL : MonoBehaviour {
  3. void Start () {
  4. string url = "http://example.com/script.php?var1=value2&var2=value2";
  5. WWW www = new WWW(url);
  6. StartCoroutine(WaitForRequest(www));
  7. }
  8. IEnumerator WaitForRequest(WWW www)
  9. {
  10. yield return www;
  11. // check for errors
  12. if (www.error == null)
  13. {
  14. Debug.Log("WWW Ok!: " + www.data);
  15. } else {
  16. Debug.Log("WWW Error: "+ www.error);
  17. }
  18. }
  19. }
more ▼
answered Feb 03 '10 at 05:24 PM
duck gravatar image
duck ♦♦
45.1k  106  160  425




[JSON Parser]


http://kimstar.pe.kr/blog/74
: JSON 개요 및 예제, 전반적인 내용에 대해서 정리된 글

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_QnA_etc&page=1&sn1&divpage=1&sn=off&ss=on&sc=on&select_arrange=hit&desc=asc&no=2616
: litJSON iOS상 serialization 이슈

여러가지 라이브러리가 있지만 간단한 simpleJSON을 고려..

http://wiki.unity3d.com/index.php/SimpleJSON
: SimpleJSON 사이트

http://blog.naver.com/whostheman?Redirect=Log&logNo=100179607893
: Simple JSON 사용 설명, 토튜님.

{
    "version": "1.0",
    "data": {
        "sampleArray": [
            "string value",
            5,
            {
                "name": "sub object"
            }
        ]
    }
}
  
여기서 sampleArray의 string value에 접근하는 방법을 보자.
 아래와 같이 일단 string 값을 파싱한다.
  
var N = JSON.Parse(the_JSON_string);
그리고 노드(Node)의 이름과 index로 접근이 가능하다.
string val = N["data"]["sampleArray"][0];