https://github.com/jeng832/blog-example/tree/master/gson2

 

jeng832/blog-example

Contribute to jeng832/blog-example development by creating an account on GitHub.

github.com

Gson은 Object mapping 방식 말고도, Json자체를 JsonObject라는 class로 만들어서 Json내에 object, 값, 배열,null 을 가져오거나, 추가, 삭제 등을 할 수 있다.

 

먼저 JsonObject에서는 Json의 요소를 구분하는 총 5가지 종류의 class가 있다.

JsonElement, JsonObject, JsonPrimitive, JsonArray, JsonNull

 

1. JsonElement

위의 다섯가지 중 JsonElement를 제외한 4가지는 JsonElement를 상속한다.

즉, JsonElement는 나머지 4가지의 부모class로 추상클래스로 정의되어 있다.

기본적으로 getter를 통해서 Json의 요소를 가져오면 기본적으로 JsonElement 형태로 받아오며, 필요에 따라서 적절히 변환해서 사용해야 한다.

 

2. JsonObject

Json에서 중괄호로 묶여서 하나의 Object를 나타낼때, 그것을 표현하기 위한 class

당연히 key-value형태로 존재하며, 실제 구현은 LinkedTreeMap으로 구현되어 있다.

 

3. JsonPrimitive

Json에서 특정 key의 value값을 나타내기 위한 class, 

숫자, 문자, Boolean 등 의 실제 값을 저장한다.

 

4. JsonArray

Json에서 [] 로 묶여서 배열을 나타내기 위한 class

index로 접근 가능하며, 실제 List와 유사하다.(알고보니 구현체도 ArrayList로 구현되어 있군...)

 

5. JsonNull

null object를 표현하기 위한 class

 

아래 Test code를 이용해서 확인 가능하다..

public class GsonTest {
    @Test
    public void testJsonObject() {
        String json =
                "{" +
                "    strKey : strValue, " +
                "    numKey: 235, " +
                "    arrKey: [arrV1, arrV2, arrV3]," +
                "    objKey: {subKey: subValue}," +
                "    numArrKey: [100, 200, 300]," +
                "    nullKey: null" +
                "}";
        JsonObject jsonObj = (JsonObject) JsonParser.parseString(json);
        System.out.println(jsonObj.isJsonPrimitive());
        System.out.println(jsonObj.isJsonObject());
        System.out.println(jsonObj.isJsonArray());
        System.out.println(jsonObj.isJsonNull());
        System.out.println(jsonObj.toString());

        System.out.println("=============== strKey ===============");
        JsonElement element = jsonObj.get("strKey");
        System.out.println(element.isJsonPrimitive());
        System.out.println(element.isJsonObject());
        System.out.println(element.isJsonArray());
        System.out.println(element.isJsonNull());
        System.out.println(element.toString());

        System.out.println("=============== numKey ===============");
        element = jsonObj.get("numKey");
        System.out.println(element.isJsonPrimitive());
        System.out.println(element.isJsonObject());
        System.out.println(element.isJsonArray());
        System.out.println(element.isJsonNull());
        System.out.println(element.toString());

        System.out.println("=============== arrKey ===============");
        element = jsonObj.get("arrKey");
        System.out.println(element.isJsonPrimitive());
        System.out.println(element.isJsonObject());
        System.out.println(element.isJsonArray());
        System.out.println(element.isJsonNull());
        System.out.println(element.toString());

        System.out.println("=============== objKey ===============");
        element = jsonObj.get("objKey");
        System.out.println(element.isJsonPrimitive());
        System.out.println(element.isJsonObject());
        System.out.println(element.isJsonArray());
        System.out.println(element.isJsonNull());
        System.out.println(element.toString());

        System.out.println("=============== nullKey ===============");
        element = jsonObj.get("nullKey");
        System.out.println(element.isJsonPrimitive());
        System.out.println(element.isJsonObject());
        System.out.println(element.isJsonArray());
        System.out.println(element.isJsonNull());
        System.out.println(element.toString());
    }
}

 

실행 결과는...

false
true
false
false
{"strKey":"strValue","numKey":235,"arrKey":["arrV1","arrV2","arrV3"],"objKey":{"subKey":"subValue"},"numArrKey":[100,200,300],"nullKey":null}
=============== strKey ===============
true
false
false
false
"strValue"
=============== numKey ===============
true
false
false
false
235
=============== arrKey ===============
false
false
true
false
["arrV1","arrV2","arrV3"]
=============== objKey ===============
false
true
false
false
{"subKey":"subValue"}
=============== nullKey ===============
false
false
false
true
null  

기본적으로 Json String을 JsonObject로 받기 위해서는 JsonParser.parseString() method를 이용해야 한다.

(해당 method는 static이므로, 걍 사용하면 된다.)

참고로 parseString의 return 은 JsonElement 이므로 변환해야 JsonObject로 받을 수 있다.

    @Test
    public void testJsonParse() {
        String json =
                "{" +
                        "    strKey : strValue, " +
                        "    numKey: 235, " +
                        "    arrKey: [arrV1, arrV2, arrV3]," +
                        "    objKey: {subKey: subValue}," +
                        "    numArrKey: [100, 200, 300]," +
                        "    nullKey: null" +
                        "}";
        JsonObject jsonObj = (JsonObject) JsonParser.parseString(json);
        jsonObj = JsonParser.parseString(json).getAsJsonObject();
    }

 

코드를 보면 알 수 있듯이 get("key")을 통해서 얻어온 값은 JsonElement이고 이를 isJsonXXX() 를 통해서 어떤 종류인지 확인 한후 getAsXXX()을 통해 변환후 사용해야 한다.

    @Test
    public void testJsonConvert(String json) {
        JsonElement elem = JsonParser.parseString(json);
        if (elem.isJsonPrimitive()) {
            JsonPrimitive primitive = elem.getAsJsonPrimitive();
            // logic for JsonPrimitive
        } else if (elem.isJsonArray()) {
            JsonArray array = elem.getAsJsonArray();
            // logic for JsonArray
        } else if (elem.isJsonObject()) {
            JsonObject object = elem.getAsJsonObject();
            // logic for JsonObject
        } else if (elem.isJsonNull()) {
            JsonNull jsonNull = elem.getAsJsonNull();
            // logic for JsonNull
        }
    }

 

개발을 하다보면 json을 통해서 정보전달을 하는 경우가 많다. 그 때 gson, jackson 등 여러가지가 library를 취향껏 사용하면 되는데, 오늘은 google에서 나온 gson을 이용한 object mapping을 설명하겠다.

 

1. gradle에 gson 추가

먼저, gson 을 사용하기 위해서 gradle에 추가해야 한다.

최신 gson은 아래 링크를 통해 확인 가능하고..

https://mvnrepository.com/artifact/com.google.code.gson/gson

 

Maven Repository: com.google.code.gson » gson

 

mvnrepository.com

이 글을 쓰는 현재 최신 버젼인 2.8.6을 활용 한다.

 

compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'

 

추가 하고 gradle sync 를 하면 완료

 

2. class 만들기

json을 class로 만들거나, class를 json으로 object mapping 시키기 위해서 우선 대상 class를 만든다.

간략히 아래와 같이 생성...

toString()은 확인을 위해 만든거라서 없어도 무방하다..

 

public class Animal {
    private int nLeg;
    private String name;

    @Override
    public String toString() {
        return "Animal[nLeg: " + nLeg + ", name: " + name + "]";
    }
}

 

3. Object mapping 하기

object mapping을 하기 위한 method는 2가지, fromJson / toJson 이다.

json -> object 는 fromJson

object -> json 은 toJson

 

매우 간단하다.

 

code로 보면 아래와 같다...

String에서 " 큰따옴표를 사용하려면 \" 를 사용해야 함을 유의!!

public class AnimalTest {

    @Test
    public void testJson() {
        Gson gson = new Gson();

        String json = "{\"nLeg\":4, \"name\": \"Bill\"}";
        Animal animal = gson.fromJson(json, Animal.class);
        System.out.println(animal);

        String reJson = gson.toJson(animal);
        System.out.println(reJson);
    }
}

 

결과는?

 

Animal[nLeg: 4, name: Bill]
{"nLeg":4,"name":"Bill"}

 

4. key 이름 변경

본인은 헝가리안 표기법을 좋아하지는 않지만, 개발조직의 coding convention상 m 이나, n 혹은 i 등을 prefix로 사용하여 class의 멤버이름을 설정해 주어야 하는 경우가 있다.

gson을 그냥 활용할 경우 class의 멤버 이름을 그대로 json의 key로 mapping 시키기 때문에, 위의 예제에 nLeg 같은 key를 사용해야 한다. 

멤버의 이름 말고 json key이름을 지정하는 방법은 gson에서 제공하는 annotation으로 해결 가능하다.

사용할 annotation은 @SerializedName("key 이름")

 

2번의 class를 아래와 같이 수정 하고 

 

import com.google.gson.annotations.SerializedName;

public class Animal {
    @SerializedName("legs")
    private int nLeg;

    @SerializedName("name")
    private String name;

    @Override
    public String toString() {
        return "Animal[nLeg: " + nLeg + ", name: " + name + "]";
    }

}

 

3번의 test code에서 json 의 key이름을 수정하여 다시 실행 해보면...

 

public class AnimalTest {

    @Test
    public void testJson() {
        Gson gson = new Gson();

        String json = "{\"legs\":4, \"name\": \"Bill\"}";
        Animal animal = gson.fromJson(json, Animal.class);
        System.out.println(animal);

        String reJson = gson.toJson(animal);
        System.out.println(reJson);
    }
}

legs 를 key로 사용해도 nLeg 변수에 값이 들어가고, 해당 class를 다시 json 화 했을 때도 지정한 key인 legs 로 바뀌는 것을 알 수 있다.

Animal[nLeg: 4, name: Bill]
{"legs":4,"name":"Bill"}

 

위의 code는 아래 github에서 확인 가능하다.

https://github.com/jeng832/blog-example/tree/master/gson

mongodb 시작하기

$ sudo service mongod start

 

mongodb shell 시작

$ mongo

 

database 종류 확인

> show databases

 

database 사용(선택)

> use {database이름}

 

collection 종류 확인

(db 선택 이후)

> show collections

 

collection 제거

> db.{collection 이름}.drop()

 

document 추가

> db.{collection 이름}.insert({문서})

db.books.insert({"a":1})
WriteResult({ "nInserted" : 1 })

 

document bulk insert

> db.{collection 이름}.insert([{문서}])

db.books.insert([{"a":1},{"b": 1}])
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})

 

document 찾기

> db.{collection 이름}.find({조건})

{조건}도 json 형태로 입력

 

document 지우기(조건 맞는 모든 document 지우기)

> db.{collection 이름}.remove({조건})

{조건}도 json 형태로 입력

 

document 지우기(조건 맞는 하나의 document 지우기)

> db.{collection 이름}.remove({조건}, true)

{조건}도 json 형태로 입력

'Development > Database' 카테고리의 다른 글

MongoDB에서 Connection Pool 구성 하기  (0) 2017.02.13
MongoDB Ubuntu에 설치하기  (0) 2017.02.10
MongoDB 에서 admin 만들기  (2) 2017.02.10

Kotlin에서 Class 선언 하는 방법에 대해서 포스팅을 했으니

Kotlin에서 Class 선언하기

 

Kotlin에서 Class 선언하기

Kotlin(코틀린)은 JetBrains에서 제작된 프로그래밍 언어로서 구글에서 Android 기본 언어로 채택 되면서 주목받는 hot한 언어가 되었다. JetBrains의 연구소가 있는 러시아 상트페테르부르크에 있는 코틀린 섬에..

ijeee.tistory.com

이번에는 Class 생성자(Constructor)에 대해서 포스팅 해보겠다.

 

Kotlin의 생성자는 주생성자(Primary Constructor)와 부생성자(Secondary Constructor)로 구분된다.

 

1. 주생성자

Kotlin을 배우면서 느낀점은 Java 개발자가 개발하면서 느꼈던 온갖 귀찮은 작업을 생략하는 언어라는 느낌이다-_-);;;

귀찮은 Java 개발자의 언어랄까......

 

 

Java에서는 모든 생성자는 method처럼 선언을 해주어야 한다 하지만 Kotlin에서는 그런 귀찮은 일을 하지 않아도 된다!!

주생성자는 class 선언하면서 생성자를 동시에 정의할 수 있는 기법이다.

방법은 class 이름 옆에 생성자의 parameter를 받고, Property 선언시

해당 값을 이용하여 초기화 해주면 된다.

 

class Animal(_nLeg:Int, _color:String) {
    val nLeg:Int = _nLeg
    val color:String = _color
    var name:String = "Tom"

    fun eat(something:String) {
        println("Eat $something")
    }

    fun cry() {
        println("Cry!!!")
    }
}

이제 Class를 사용하려면 아래와 같이 주생성자의 인자를 넘겨주어야 한다.

val myAnimal = Animal(4, "yellow")

자 이제 귀찮은 Java 개발자를 위해 한번더 생략!

생성자의 인자도 선언해줘야 하고 Property도 선언해줘야 하는데, 귀찮으니 한방에 쓰자!!!

 

생성자의 인자를 적어줄때 val, var을 적으면, 해당 인자가 바로 class의 property가 된다.

이 글을 보는 사람이라면 알겠지만 val은 불변, var은 변화가 가능한 Property

class Animal(val nLeg:Int, val color:String) {
    var name:String = "Tom"

    fun eat(something:String) {
        println("Eat $something")
    }

    fun cry() {
        println("Cry!!!")
    }
}

예제에서 보다시피 생성자를 통해서 초기화 하기 싫은 변수는 주생성자의 인자로 넣지 않고 따로 선언할 수 있다.

그런데 실제 개발을 하다보면 생성자에서 변수 초기화만 하지 않고 뭔가 로직을 넣어야 하는 상황이 오는데,

주생성자가 Class이름과 함께 정의를 하게된다면...

로직은 어떻게 넣을까???

 

Kotlin에서는 주생성자의 추가 로직을 위해 init이라고 하는 키워드를 통해 초기화 블록을 제공한다.

class Animal(val nLeg:Int, val color:String) {
    var name:String = "Tom"
    init {
        println("=== Primary Init block ===")
        println("nLeg: $nLeg, color: $color, name: $name")
        // Do something!!
    }

    fun eat(something:String) {
        println("Eat $something")
    }

    fun cry() {
        println("Cry!!!")
    }
}

 

2. 부생성자

부생성자는 Java의 생성자와 유사하다. 여러개의 생성자를 만들수 있고 생성자에서 어떤 동작을 할지 정의를 해주어야 한다.  부 생성자임을 알려주는 키워드는 constructor

단, 부생성자는 반드시 주생성자와 같이 사용되어야 한다. 부생성자는 주생성자를 호출한다.

class Animal(val nLeg:Int, val color:String) {
    var name:String = "Tom"
    init {
        println("=== Primary Init block ===")
        println("nLeg: $nLeg, color: $color, name: $name")
        // Do something!!
    }

    constructor(_nLeg:Int, _color:String, _name:String) : this(_nLeg, _color) {
        println("=== Secondary constructor start ===")
        this.name = _name
        println("=== Secondary constructor end ===")
    }

    fun eat(something:String) {
        println("Eat $something")
    }

    fun cry() {
        println("Cry!!!")
    }
}

부생성자 선언 뒤에 : this()를 통해서 주생성자의 인자를 전달해주어야 한다.

부생성자를 호출하게 되면 주생성자와 초기화 블록의 순서는 어떻게 될까??

val myAnimal = Animal(4, "yellow", "Smith")

 

=== Primary Init block ===
nLeg: 4, color: yellow, name: Tom
=== Secondary constructor start ===
=== Secondary constructor end ===

실행 결과에서 알수 있듯이 주생성자 -> 초기화 블록 -> 부생성자 순서로 호출된다.

 

포스팅에 사용된 소스는 아래의 github에서 확인 가능하다.

 

https://github.com/jeng832/blog-example/tree/master/24_Kotlin%20class%20constructor%20%EC%A0%95%EB%A6%AC

IntelliJ에서 Kotlin으로 작성된 소스를 Java 코드로 확인할 수 있다.

Decompiler 기능을 이용한 것인데..

 

Tools > Kotlin > Show Kotlin Bytecode 선택

Kotlin Bytecode 탭(?)에서 Decompile 버튼 클릭

 

Decompile 된 java 소스 확인

'Development > Kotlin' 카테고리의 다른 글

Kotlin class constructor 정리  (0) 2019.10.14
Kotlin에서 Class 선언하기  (0) 2019.10.09

+ Recent posts