[android] Jackson parser sample With Volleyer

Volley를 더 쉽고 강력하게, Volley Extensions 를 읽다 보니 Jackson이라는 JSON parser가 성능이 좋다는 말이 나와서 예제를 만들어 봤다.

(고수들은 왜 더 쉬운 예제를 만들어주지 않는 걸까? ㅠㅠ)

 

 

일단 http://susemi99.kr/3089 와 기본적인 설정은 같고 jackson-databind 만 추가됐다.

android {
    ...
    packagingOptions{
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/NOTICE'
    }

  dexOptions {
        javaMaxHeapSize "4g" //specify the heap size for the dex process
        preDexLibraries = false //delete the already predexed libraries
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.navercorp.volleyextensions:volleyer:2.0.+'
    compile 'com.mcxiaoke.volley:library:1.0.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.6.+'
}

 

 

하나의 객체만 갖고 있을 때

이런  JSON 타입일 때는

{
  "name":"title1",
  "url":"http://google.co.kr/1"
}

 

파싱을 해서 넣어둘 클래스를 만들고

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class MyItem
{
  @JsonProperty("name") // 이름이 같을 때는 굳이 안 써도 된다.
  public String name;

  public String url;
}

 

.withTargetClass()에 추가해서 호출하면 된다.

private void callJackson1()
{
  Volleyer.volleyer().get("http://test.susemi99.kr/jackson1.json")
                     .withTargetClass(MyItem.class)
                     .withListener(listener1)
                     .execute();
}
 
private Response.Listener<MyItem> listener1 = new Response.Listener<MyItem>()
{
  @Override
  public void onResponse(MyItem item)
  {
    textResult.setText("==== jackson1 ====\n");
    textResult.append(item.name + ", " + item.url);
  }
};

 

 

같은 종류 객체의 배열일 때

같은 종류 여러 개가 오는 경우도 있다.

[
  {
    "name":"title1",
    "url":"http://google.co.kr/1"
  },
  {
    "name":"title2",
    "url":"http://google.co.kr/2"
  }
]

 

이럴 때는 MyItem[].class를 넣으면 된다.

private void callJackson2()
{
  Volleyer.volleyer().get("http://test.susemi99.kr/jackson2.json")
                     .withTargetClass(MyItem[].class)
                     .withListener(listener2)
                     .execute();
}
 
private Response.Listener<MyItem[]> listener2 = new Response.Listener<MyItem[]>()
{
  @Override
  public void onResponse(MyItem[] items)
  {
    textResult.setText("==== jackson2 ====\n");

    for (MyItem item : items)
    {
      textResult.append(item.name + ", " + item.url + "\n");
    }
  }
};

 

 

배열 형태의 top element가 있을 때

올바른 형태라고 볼 수는 없지만, 최상위에 element가 있을 때도 있다.

이런 경우는 저 result가 필요가 없지만, 그래도 top이 아닐 때를 대비해서 적어 놓는다.

{
  "result":[
    {
      "name":"title1",
      "url":"http://google.co.kr/1"
    },
    {
      "name":"title2",
      "url":"http://google.co.kr/2"
    },
    {
      "name":"title3",
      "url":"http://google.co.kr/3"
    }]
}

 

이런 경우는 한 번 더 감싸야 한다.

다른 방법도 있을 것 같은 느낌이긴 한데, 못 찾겠다 ;;;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.ArrayList;

@JsonIgnoreProperties(ignoreUnknown = true)
public class MyItems
{
  @JsonProperty("result")
  public ArrayList<MyItem> items;
}

 

호출하는 방법은 비슷하다.

private void callJackson3()
{
  Volleyer.volleyer().get("http://test.susemi99.kr/jackson3.json")
                     .withTargetClass(MyItems.class)
                     .withListener(listener3)
                     .execute();
}

private Response.Listener<MyItems> listener3 = new Response.Listener<MyItems>()
{
  @Override
  public void onResponse(MyItems myItems)
  {
    textResult.setText("==== jackson3 ====\n");

    for (MyItem item : myItems.items)
    {
      textResult.append(item.name + ", " + item.url + "\n");
    }
  }
};

 

 

객체를 가진 top element가 있을 때

최상위에 element가 있고, 그 밑에 객체가 있는 변태 형태도 가능하다.

{
  "result":
  {
    "name":"title1",
    "url":"http://google.co.kr/1"
  }
}

 

이거를 위해 또 하나의 클래스를 만든다.

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class MyItemParent
{
  @JsonProperty("result")
  public MyItem item;
}

 

호출 방식도 크게 다르지 않다.

private void callJackson4()
{
  Volleyer.volleyer().get("http://test.susemi99.kr/jackson4.json")
                     .withTargetClass(MyItemParent.class)
                     .withListener(listener4)
                     .execute();
}

private Response.Listener<MyItemParent> listener4 = new Response.Listener<MyItemParent>()
{
  @Override
  public void onResponse(MyItemParent myItemParent)
  {
    textResult.setText("==== jackson4 ====\n");
    textResult.append(myItemParent.item.name + ", " + myItemParent.item.url + "\n");
  }
};

 

 

느낀 점

확실히 일일이 파싱을 하는 것보다 편하다.

다만 굳이 클래스를 안 만들고 한 클래스 안에서 다 해도되는 경우라면 좀 번거로워질 수 있을 것 같다.

 

 

Download Source

source : https://github.com/susemi99/VolleyerJacksonSample

 

 

Convert to JSON

다시 JSON으로 돌리고 싶다면

ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(item);

이렇게 하면 된다.

도움 받은 곳 : http://stackoverflow.com/a/15786175/1025379