[Golang] JSON 다루기

반응형

Go에서는 json 패키지 이용해서 JSON 데이터를 읽고 쓸 수 있다. 오늘은 Go 구조체와 json 패키지를 이용해 JSON 데이터를 읽고 쓰는 방법에 대하여 정리하겠다. 먼저 Go의 json 패키지에 있는 두 함수에 대하여 알아보자.

 

마샬링과 언마샬링

마샬링

Go 자료형을 JSON 데이터로 변경합니다. Marshal 함수를 사용한다.

func Marshal(v interface{}) ([]byte, error)

언마샬링

마샬링과 반대로 JSON 데이터를 Go 자료형으로 변환합니다. Unmarshal 함수를 이용한다.

func Unmarshal(data []byte, v interface{}) error

 


 

 

이제부터 예제를 통해 Go에서 JSON 다루는 방법에 대하여 알아보자.

Simple JSON

우선 간단한 JSON 다루는 방법이다.

type Movie struct {
    Id    int
    Title string
    Adult bool
    Year  int
}

func main() {
    m := Movie{1, "The Dark Knight", false, 2008}
    b, err := json.Marshal(m)

    if err != nil {
        log.Fatalf("JSON marshaling failed: %s", err)
    }

    fmt.Println(string(b))
}

실행 결과는 다음과 같다.

{
  "Id": 1,
  "Title": "The Dark Knight",
  "Adult": false,
  "Year": 2008
}

 

 

 

마샬링 되는 결과의 JSON 필드의  key 이름을 변경할 수 있다.

구조체 필드 선언에 태그(json:"이름")를 사용하면 된다.

type Movie struct {
    Id    int    `json:"id"`
    Title string `json:"title"`
    Adult bool   `json:"adult"`
    Year  int    `json:"released"`
}

실행 결과는 다음과 같다. 설정한 이름들로 나오는 것을 확인할 수 있다.

{
  "id": 1,
  "title": "The Dark Knight",
  "adult": false,
  "released": 2008
}

 

 

 

필드에 값이 없을 경우 마샬링되는 결과에 포함시키지 않을 수도 있다.

omitempty 옵션을 추가하여 해당 필드를 JSON data로 변환하지 않다. omitempty 옵션을 사용하면 false, 0, a nil pointer, a nil interface value, 그리고 비어있는 array, slice, map, string는 변환되지 않는다.

type Movie struct {
    Id    int    `json:"id"`
    Title string `json:"title"`
    Adult bool   `json:"adult,omitempty"`
    Year  int    `json:"released"`
}

func main() {
    m := Movie{1, "The Dark Knight", false, 2008}
    b, err := json.Marshal(m)

    if err != nil {
        log.Fatalf("JSON marshaling failed: %s", err)
    }

    fmt.Println(string(b))
}

실행 결과는 다음과 같다. adult 필드가 false이기 때문에 무시되어 나온다.

{
  "id": 1,
  "title": "The Dark Knight",
  "released": 2008
}

 

 

 

Unmarshal를 이용해서 JSON 데이터를 Go의 값으로 변환할 수 있다.

func main() {

    data := []byte(`
        {
          "id": 1,
          "title": "The Dark Knight",
          "adult": false,
          "released": 2008
        }
        `)

    var movie Movie
    err := json.Unmarshal(data, &movie)
    if err != nil {
        log.Fatalf("JSON unmarshaling failed: %s", err)
        os.Exit(1)
    }

    fmt.Printf("%+v\n", movie)
}

실행 결과는 다음과 같다.

{Id:1 Title:The Dark Knight Adult:false Year:2008}

 

 

Array JSON

Array JSON 마샬링 하는 것을 해보자.

func main() {
    m := []Movie{
        {1, "The Dark Knight", false, 2008},
        {2, "The Godfather", true, 1972},
        {3, "GoodFellas", true, 1990},
    }

    b, err := json.Marshal(m)
    if err != nil {
        log.Fatalf("JSON marshaling failed: %s", err)
    }

    fmt.Println(string(b))
}

실행 결과는 다음과 같다.

[
  {
    "id": 1,
    "title": "The Dark Knight",
    "released": 2008
  },
  {
    "id": 2,
    "title": "The Godfather",
    "adult": true,
    "released": 1972
  },
  {
    "id": 3,
    "title": "GoodFellas",
    "adult": true,
    "released": 1990
  }
]

 

 

 

Nested JSON

아래와 같이 장르가 추가된 중첩된 JSON 데이터를 처리할 경우가 생길 수 있다.

{
  "id": 1,
  "title": "The Dark Knight",
  "released": 2008,
  "genre": {
    "id": 1,
    "name": "drama"
  }
}

이럴 경우는 struct를 다음과 같이 구성하면 된다.

type Movie struct {
    Id    int    `json:"id"`
    Title string `json:"title"`
    Adult bool   `json:"adult,omitempty"`
    Year  int    `json:"released"`
    Genre Genre  `json:"genre"`
}

type Genre struct {
    Id   int    `json:"id"`
    Name string `json:"name"`
}

아니면 아래와 같이 작성해도 상관없다.

type Movie struct {
    ID    int    `json:"id"`
    Title string `json:"title"`
    Adult bool   `json:"adult,omitempty"`
    Year  int    `json:"released"`
    Genre struct {
        ID   int    `json:"id"`
        Name string `json:"name"`
    } `json:"genre"`
}

 


 

저 같은 경우는 JSON 데이터를 다루기 위해 Go struct를 만들어야 하는 경우가 많은데요. 이런 작업은 JSON 필드가 많은 경우는 조금 귀찮은 작업이다. 아래 사이트를 이용하면 귀찮음을 덜 수 있다. 해당 사이트는 JSON를 입력하면 Go struct 변환해준다.

Inline type definitions 해제하면 아래와 같이 나온다.