encoding/json과 구조체
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 76번째.
encoding/json 패키지를 사용하면 Go 구조체를 JSON으로 변환하거나 그 반대로 변환할 수 있습니다. 이는 API, 설정 파일 및 데이터 저장에 필수적입니다. 구조체 태그(Struct tags)는 필드가 JSON 키에 매핑되는 방식을 제어합니다.
구조체를 JSON으로 변환하려면 json.Marshal을 사용하세요:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","email":"alice@example.com","age":30}
}`json:"name"`와 같은 구조체 태그는 JSON 키 이름을 지정합니다. 태그가 없으면 Go는 필드 이름을 직접 사용합니다. 내보낸 필드(대문자로 시작하는 필드)만 JSON 출력에 포함됩니다.
JSON을 다시 구조체(struct)로 변환하려면 json.Unmarshal을 사용하세요:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // Bob일반적인 태그 옵션에는 제로 값을 건너뛰는 omitempty와 필드를 완전히 무시하는 -가 포함됩니다:
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}omitempty를 사용하면, Price가 0인 경우 JSON에 나타나지 않습니다. Internal 필드는 값에 관계없이 절대 포함되지 않습니다.
챌린지
쉬움Go 구조체와 JSON 간의 변환을 수행하는 영화 카탈로그 시스템을 만들어 봅시다! 구조체 태그를 사용하여 JSON 필드 이름을 제어하면서, 구조체를 JSON으로 마샬링(marshaling)하고 JSON을 다시 구조체로 언마샬링(unmarshaling)하는 연습을 하게 됩니다.
코드는 다음 두 파일로 구성됩니다:
movie.go: 적절한 JSON 태그를 사용하여 영화 데이터 모델을 정의합니다.다음 필드와 JSON 매핑을 가진
Movie구조체를 생성하세요:Title(string)은"title"에 매핑Director(string)은"director"에 매핑Year(int)는"year"에 매핑Rating(float64)은"rating"에 매핑하며, 평점이 없는 영화에 평점 필드가 표시되지 않도록omitempty를 추가InternalID(string)은"-"를 사용하여 JSON에서 완전히 제외
Movie를 JSON 문자열로 변환하는
ToJSON(m Movie) string함수를 작성하세요. 또한 JSON 문자열을 다시 Movie 구조체로 파싱하는FromJSON(jsonStr string) Movie함수를 작성하세요.main.go: 양방향 JSON 변환을 시연합니다.작업 유형(
"encode"또는"decode")을 읽습니다."encode"의 경우: 영화 상세 정보(제목, 감독, 연도, 평점)를 별도의 줄에서 읽습니다. InternalID가"internal-123"인 Movie를 생성하고, 이를 JSON으로 변환하여 결과를 출력합니다."decode"의 경우: JSON 문자열을 읽고, 이를 Movie 구조체로 변환한 후 다음 형식으로 영화 상세 정보를 출력합니다:Title: [title] Director: [director] Year: [year] Rating: [rating]평점은 소수점 첫째 자리까지 표시합니다. 평점이 0(JSON에 존재하지 않음)인 경우, 대신
Rating: N/A를 출력합니다.
다음 입력이 제공됩니다:
- 1행: 작업 유형 (
"encode"또는"decode") - encode의 경우: 제목, 감독, 연도, 평점 (4행)
- decode의 경우: JSON 문자열 (1행)
예를 들어, 다음과 같이 입력되면:
encode
Inception
Christopher Nolan
2010
8.8출력은 다음과 같아야 합니다:
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}"-" 태그 때문에 InternalID가 출력에 나타나지 않는 점에 유의하세요.
그리고 다음과 같이 입력되면:
encode
The Matrix
Wachowskis
1999
0출력은 다음과 같아야 합니다:
{"title":"The Matrix","director":"Wachowskis","year":1999}평점이 0이고 omitempty가 설정되어 있어 rating이 생략된 점에 유의하세요.
그리고 다음과 같이 입력되면:
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}출력은 다음과 같아야 합니다:
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6그리고 다음과 같이 입력되면:
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}출력은 다음과 같아야 합니다:
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/A치트 시트
encoding/json 패키지는 json.Marshal과 json.Unmarshal을 사용하여 Go 구조체를 JSON으로 변환하거나 그 반대로 변환합니다.
구조체를 JSON으로 변환하려면:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","email":"alice@example.com","age":30}JSON을 다시 구조체로 변환하려면:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // Bob구조체 태그(Struct tags)는 JSON 필드 매핑을 제어합니다:
`json:"name"`- 필드를 JSON 키 "name"에 매핑합니다`json:"price,omitempty"`- 값이 제로 값(zero value)인 경우 필드를 생략합니다`json:"-"`- 필드를 JSON에서 완전히 제외합니다
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}내보내기된 필드(대문자로 시작하는 필드)만 JSON 출력에 포함됩니다.
직접 해보기
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 연산 유형 읽기
operation, _ := reader.ReadString('\n')
operation = strings.TrimSpace(operation)
if operation == "encode" {
// 영화 상세 정보 읽기
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
director, _ := reader.ReadString('\n')
director = strings.TrimSpace(director)
yearStr, _ := reader.ReadString('\n')
yearStr = strings.TrimSpace(yearStr)
year, _ := strconv.Atoi(yearStr)
ratingStr, _ := reader.ReadString('\n')
ratingStr = strings.TrimSpace(ratingStr)
rating, _ := strconv.ParseFloat(ratingStr, 64)
// TODO: 읽어온 값들로 Movie 구조체 생성하기
// InternalID를 "internal-123"으로 설정하기
// ToJSON을 사용하여 JSON으로 변환하고 결과 출력하기
} else if operation == "decode" {
// JSON 문자열 읽기
jsonStr, _ := reader.ReadString('\n')
jsonStr = strings.TrimSpace(jsonStr)
// TODO: FromJSON을 사용하여 JSON을 Movie로 변환하기
// 요구된 형식으로 영화 상세 정보 출력하기
// 평점 포맷팅을 위해 fmt.Sprintf("%.1f", rating) 사용하기
// 평점이 0이면 대신 "Rating: N/A" 출력하기
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서11표준 라이브러리 & OOP
io.Reader & io.Writersort.Interfacefmt.Stringer 인터페이스encoding/json과 구조체http.Handler 인터페이스요약 - REST API 모델