2. Assets에 Json파일을 넣자.

2019. 2. 24. 19:05개발기록/Smite Items

반응형

> [1. 밑그림](https://zerodice0.tistory.com/122)에 이어서 번역된 json파일을 들고 작업을 하기 시작했다.


대학교 졸업하고나서 몬스터헌터4가 나올 무렵, 일본 Wiki를 크롤링해서 기계번역해주는 어플을 만들었으니까... 거진 4년만에 안드로이드 애플리케이션을 만드는 셈인가. Java문법도 거의 기억이 나지 않는지라, Kotlin을 사용하기로 했다.


> `Master/Detail Flow`은 리스트를 표시해주고, 리스트를 클릭하면 아이템의 자세한 내용을 표시해준다.


간단하게 리스트에 아이템을 뿌려주고, 아이템을 클릭하면 자세한 설명을 표시해주면 될 것 같았다. `New Project`에서 `Master/Detail Flow`를 생성했다. 만들고 실행해보니 더미 데이터를 리스트에 뿌려주고 있는데, 오래간만에 보니 구조파악이 잘 되지 않았다. 그래도 더듬더듬 구조를 더듬어서 만들거보기로 했다.


```

┣ ItemDetailActivity // List에 표시된 Item을 클릭하면, ItemDetailActivity가 표시된다.

┣ ItemDetailFragment // ItemDetailActivity에 표시되는 Fragment이다.

└ ItemListActivity //List를 표시해주는 main Activity


```


대충 구조는 위와 같았고, assets 폴더를 생성한 뒤 번역이 추가된 Json파일을 넣어줘야 했다.

```

app

┣manifests

┣java

┣generatedJava

┣assets // assets 폴더는 자동생성되지 않는다. app을 우클릭해서, New > Folder > Assets Folder를 선택하자.

┣res

``` 


용량을 조금이라도 줄일 수 있을까 싶어서, [JSON Minifier, Web Toolkit Online](https://www.webtoolkitonline.com/json-minifier.html)에 들러 Json파일을 minify했다.


아이템들을 리스트에 표시해주기 위해선, Assets에 넣어둔 json파일을 읽어와야했다. 다행히 읽어오는 방법은 어렵지 않았다. InputStream을 사용해서 파일을 열고, bufferedReader를 사용해서 문자열로 읽어들일 수 있었다. 이후 JSONArray/JSONObject타입을 생성할 때 생성자에 이 문자열을 전달해주면, 문자열을 기반으로 json 데이터를 얻을 수 있다.


```

val inputStream:InputStream = assets.open("items.json")

val strData:String = inputStream.bufferedReader().use{it.readText()}

val jsonArrayData = JSONArray(strData)

```


Smite 홈페이지에서 호출하는 API로 가져왔던 json데이터는 배열의 형태이므로, JSONArray를 사용해서 가져왔다. `ItemListActivity`의 코드를 따라가보니, `setupRecyclerView`에 더미 데이터를 넘겨주는 코드가 보인다. 별 생각없이 JSONArray를 넘겨주려고하니, Type Mismatched가 표시된다.


Mutable List를 만들어줘야 하는데, 데이터 클래스를 만들어줘야 할 것 같았다. 굳이 데이터 클래스를 만들어주고싶진 않았기에, 몇 시간동안 검색을 하다가 결국 포기하고 데이터 클래스를 만들기 시작했다.


```

data class Menuitem(

    val Description:String,

    val Description_kr:String,

    val Value:String

)


data class ItemDescription(

    val Description: String,

    val Description_kr: String,

    val MenuItems: ArrayList<Menuitem>,

    val SecondaryDescription: String,

    val SecondaryDescription_kr: String

)


data class Item(

    val ChildItemId:Int,

    val DeviceName:String,

    val IconId:Int,

    val ItemDescription:ItemDescription,

    val ItemId: Int,

    val ItemTier: Int,

    val Price: Int,

    val RestrictedRoles: String,

    val RootItemId: Int,

    val ShortDesc: String,

    val StartingItem: Boolean,

    val Type: String,

    val itemIcon_URL: String,

    val ret_msg: String? = null

)

```

Json lint에서 각 구조체를 확인하고, 단순작업을 통해 데이터 클래스를 만들었다. 이제 MutableList<Item>을 만들어준 뒤, 루프를 돌면서 값을 추가해주면 된다.


```

val items:MutableList<Item> = mutableListOf()


for(i in 0.until(jsonArrayData.length()-1)) {

    val itemObject = jsonArrayData.getJSONObject(i)

    val itemObjectDescription = itemObject.getJSONObject("ItemDescription")

    val arrayMenuItem = itemObjectDescription.getJSONArray("Menuitems")

    val menuItems:ArrayList<Menuitem> = arrayListOf()


    for(j in 0.until(arrayMenuItem.length()-1)) {

        val menuItemObject = arrayMenuItem.getJSONObject(j)

        val desc:String = menuItemObject.getString("Description")

        val descKr:String = menuItemObject.getString("Description_kr")

        val value:String = menuItemObject.getString("Value")


        menuItems.add(Menuitem(desc, descKr, value))

    }


    val item = Item(

        itemObject.getInt("ChildItemId"),

        itemObject.getString("DeviceName"),

        itemObject.getInt("IconId"),

        ItemDescription(

            itemObject.getJSONObject("ItemDescription").getString("Description"),

            itemObject.getJSONObject("ItemDescription").getString("Description_kr"),

            menuItems,

            itemObject.getJSONObject("ItemDescription").getString("SecondaryDescription"),

            itemObject.getJSONObject("ItemDescription").getString("SecondaryDescription_kr")

        ),

        itemObject.getInt("ItemId"),

        itemObject.getInt("ItemTier"),

        itemObject.getInt("Price"),

        itemObject.getString("RestrictedRoles"),

        itemObject.getInt("RootItemId"),

        itemObject.getString("ShortDesc"),

        itemObject.getBoolean("StartingItem"),

        itemObject.getString("Type"),

        itemObject.getString("itemIcon_URL"),

        itemObject.getString("ret_msg")

    )


    items.add(item)

}

```

파싱을 하면 쓸데없이 코드가 길어져서 최대한 피하고 싶었지만, 우선은 이렇게 처리를 했다. 완성된 MutableList<Item>을 `setupRecyclerView`의 더미데이터 대신 넘겨주니, 아이템 이름이 잘 표시된다. Detail과 url형식으로 된 아이콘만 처리하면, 일단 프로토타입의 뼈대는 완성될 듯 했다.

반응형

'개발기록 > Smite Items' 카테고리의 다른 글

[스마이트]일단 뼈대는 완성했다.  (0) 2019.03.04
1. 밑그림  (0) 2019.02.21