가장 빨리 만나는 Go 언어 Unit 51.1 구조체 활용하기

저작권 안내
  • 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
  • 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.

JSON 문서 사용하기


이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07



구조체 활용하기

앞에서는 JSON 문서가 키-값 1단계의 단순한 구조였습니다. 이번에는 구조체를 사용하여 좀 더 복잡한 형태인 JSON 문서를 처리해보겠습니다(배열, 키-배열, 키-값 조합).

package main

import (
	"encoding/json"
	"fmt"
)

type Author struct {
	Name  string
	Email string
}

type Comment struct {
	Id      uint64
	Author  Author // Author 구조체
	Content string
}

type Article struct {
	Id         uint64
	Title      string
	Author     Author    // Author 구조체
	Content    string
	Recommends []string  // 문자열 배열
	Comments   []Comment // Comment 구조체 배열
}

func main() {
	doc := `
	[{
		"Id": 1,
		"Title": "Hello, world!",
		"Author": {
			"Name": "Maria",
			"Email": "maria@example.com"
		},
		"Content": "Hello~",
		"Recommends": [
			"John",
			"Andrew"
		],
		"Comments": [{
			"id": 1,
			"Author": {
				"Name": "Andrew",
				"Email": "andrew@hello.com"
			},
			"Content": "Hello Maria"
		}]
	}]
	`

	var data []Article // JSON 문서의 데이터를 저장할 구조체 슬라이스 선언

	json.Unmarshal([]byte(doc), &data) // doc의 내용을 변환하여 data에 저장

	fmt.Println(data) // [{1 Hello, world! {Maria maria@exa... (생략)
}
실행 결과
[{1 Hello, world! {Maria maria@example.com} Hello~ [John Andrew] [{1 {Andrew andrew@hello.com} Hello Maria}]}]

다음은 JSON 문서의 구조입니다.

Id1
TitleHello, world!
AuthorNameMaria
Emailmaria@example.com
ContentHello~
RecommendsJohn
Andrew
CommentsId1
AuthorNameAndrew
EmailAndrew@hello.com
ContentHello Maria

표 51-1 JSON 문서의 구조

읽어올 JSON 문서의 구조에 맞추어서 구조체를 작성합니다.

type Article struct {
	Id         uint64
	Title      string
	Author     Author    // Author 구조체
	Content    string
	Recommends []string  // 문자열 배열
	Comments   []Comment // Comment 구조체 배열
}

구조체 안에 필드를 지정합니다. JSON은 필드 안에 다시 객체(Object)나 배열이 들어가는 방식이므로 이에 맞추어 다른 구조체를 넣어줍니다. 하위 객체이면 구조체를 그대로 넣고 배열이라면 구조체를 배열로 만듭니다.

예제는 게시판과 댓글을 구조체로 표현했습니다. 따라서 게시물이 여러 개인 배열 형태일 것이므로 데이터를 저장할 변수도 슬라이스 형태로 선언합니다.

var data []Article // JSON 문서의 데이터를 저장할 구조체 슬라이스 선언

json.Unmarshal 함수를 사용하여 값을 가져옵니다.

json.Unmarshal([]byte(doc), &data) // doc의 내용을 변환하여 data에 저장

이번에는 데이터를 JSON 형태로 변환해보겠습니다.

package main

import (
	"encoding/json"
	"fmt"
)

type Author struct {
	Name  string
	Email string
}

type Comment struct {
	Id      uint64
	Author  Author // Author 구조체
	Content string
}

type Article struct {
	Id         uint64
	Title      string
	Author     Author    // Author 구조체
	Content    string
	Recommends []string  // 문자열 배열
	Comments   []Comment // Comment 구조체 배열
}

func main() {
	data := make([]Article, 1) // 값을 저장할 구조체 슬라이스 생성

	data[0].Id = 1
	data[0].Title = "Hello, world!"
	data[0].Author.Name = "Maria"
	data[0].Author.Email = "maria@example.com"
	data[0].Content = "Hello~"
	data[0].Recommends = []string{"John", "Andrew"}
	data[0].Comments = make([]Comment, 1)
	data[0].Comments[0].Id = 1
	data[0].Comments[0].Author.Name = "Andrew"
	data[0].Comments[0].Author.Email = "andrew@hello.com"
	data[0].Comments[0].Content = "Hello Maria"

	doc, _ := json.Marshal(data) // data를 JSON 문서로 변환

	fmt.Println(string(doc)) // [{"Id":1,"Title":"Hello, world!","Au... (생략)
}
실행 결과
[{"Id":1,"Title":"Hello, world!","Author":{"Name":"Maria","Email":"maria@example.com"},"Content":"Hello~","Recommends":["John","Andrew"],"Comments":[{"Id":1,"Author":{"Name":"Andrew","Email":"andrew@hello.com"},"Content":"Hello Maria"}]}]

게시물 데이터를 저장할 슬라이스를 선언하고 make 함수로 공간을 할당합니다. 그리고 데이터를 채워넣은 뒤 json.Marshal 함수를 사용하여 JSON 문서로 변환합니다.

data := make([]Article, 1) // 값을 저장할 구조체 슬라이스 생성

// ... 생략 ...

doc, _ := json.Marshal(data) // data를 JSON 문서로 변환

패키지에서 함수(변수, 상수)를 외부에 노출할 때 이름의 첫 글자를 대문자로 만드는 것처럼 구조체도 같은 규칙으로 동작합니다. 즉 JSON 등으로 외부에 노출할 때는 구조체 필드의 첫 글자는 대문자로 만듭니다. 따라서 구조체 필드의 첫 글자를 소문자로 만들면 JSON 문서에 해당 필드는 포함되지 않습니다.

구조체 필드가 대문자로 시작하면 JSON 문서 안의 키도 대문자로 시작하게 됩니다. 여기서 JSON 문서 안의 키를 소문자로 시작하고 싶다면 다음과 같이 구조체 필드에 태그를 지정해줍니다.

  • 필드명 자료형 `json:"키"`
type 구조체명 struct {
	필드명 자료형 `json:"키"`
}
type Author struct {
	Name  string `json:"name"` // 구조체 필드에 태그 지정
	Email string `json:"email"`
}

type Comment struct {
	Id      uint64 `json:"id"`
	Author  Author `json:"author"`
	Content string `json:"content"`
}

type Article struct {
	Id         uint64    `json:"id"`
	Title      string    `json:"title"`
	Author     Author    `json:"author"`
	Content    string    `json:"content"`
	Recommends []string  `json:"recommends"`
	Comments   []Comment `json:"comments"`
}

태그는 문자열 형태이며 문자열 안에 " " (따옴표)가 포함되므로 ` ` (백쿼트)로 감싸줍니다. 그리고 JSON 문서이므로 `json:"키"` 형식으로 키 이름을 직접 지정합니다. 여기서 키 이름은 구조체 필드와 같을 필요는 없습니다.

태그를 지정한 구조체로 JSON 문서를 만들면 다음과 같이 키를 소문자로 만들 수 있습니다.

[
  {
    "id": 1,
    "title": "Hello, world!",
    "author": {
      "name": "Maria",
      "email": "maria@example.com"
    },
    "content": "Hello~",
    "recommends": [
      "John",
      "Andrew"
    ],
    "comments": [
      {
        "id": 1,
        "author": {
          "name": "Andrew",
          "email": "andrew@hello.com"
        },
        "content": "Hello Maria"
      }
    ]
  }
]

구조체 태그
구조체 태그는 JSON 문서를 만들거나, 타입 확인, 리플렉션(reflect 패키지)에서 사용할 수 있습니다. 자세한 내용은 다음 링크를 참조하기 바랍니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

2015-06-01