Go에서 커스텀 JSON 직렬화 방법은 무엇인가요?
_____A: 기본적으로 Go의 `encoding/json` 패키지는 구조체 태그나 필드 이름을 기준으로 JSON 인코딩을 수행합니다. 하지만 특정 필드 포맷 변경, 조건부 직렬화, 혹은 복잡한 변환 로직이 필요할 때 커스텀 JSON 직렬화를 구현할 수 있습니다.
Q: Go에서 커스텀 JSON 직렬화를 구현하려면 어떻게 해야 하나요?
A: `encoding/json` 패키지에서 제공하는 `Marshaler` 인터페이스(`MarshalJSON() ([]byte, error)`)를 구조체 혹은 타입에 구현하면 됩니다. 이 메서드 내에서 원하는 JSON 형식을 직접 생성해 반환할 수 있습니다.
Q: `MarshalJSON` 메서드 예제를 보여주세요.
```go
type User struct {
Name string
Age int
}
func (u User) MarshalJSON() ([]byte, error) {
// 예를 들어 Name을 소문자로 변환해서 직렬화
return json.Marshal(struct {
Name string `json:"name"`
Age int `json:"age"`
}{
Name: strings.ToLower(u.Name),
Age: u.Age,
})
}
```
Q: 커스텀 JSON 직렬화에서 주의할 점은?
A:
- `MarshalJSON` 메서드는 무한 재귀를 피하기 위해 직접 `json.Marshal`을 호출할 때 원본 타입이 아닌 별도의 익명 타입이나 구조체를 활용하는 것이 좋습니다.
- 반드시 JSON 형식을 반환해야 하며, 반환하는 바이트는 반드시 유효한 JSON이어야 합니다.
- 에러 처리도 잊지 말아야 합니다.
Q: JSON 직렬화 이외에 역직렬화도 커스텀 가능하나요?
A: 네, `json.Unmarshaler` 인터페이스의 `UnmarshalJSON([]byte) error` 메서드를 구현하면 커스텀 JSON 역직렬화가 가능합니다.
Q: 커스텀 직렬화를 구현할 때 왜 인터페이스를 사용하는가요?
A: `encoding/json` 패키지는 타입이 `json.Marshaler`를 구현했는지 확인 후, 구현되어 있으면 해당 메서드를 호출하여 JSON 변환을 진행합니다. 따라서 커스텀 직렬화는 이 인터페이스 구현 방식을 통한 확장이 자연스럽고 표준적인 방법입니다.
Q: 간단한 커스텀 직렬화 대안이 있나요?
A: 단순한 경우에는 struct 태그(`json:"필드명,omitempty"`)나 기본 타입 변환을 이용할 수 있지만, 복잡하거나 조건부 로직이 필요할 땐 `MarshalJSON` 구현이 더 유용합니다.
Q: Go에서 커스텀 JSON 직렬화는 어디에 활용되나요?
A:
- 날짜 및 시간 포맷 컨트롤
- 내부 필드값 가공 또는 숨김 처리
- 필드 이름 변경이나 추가 계산 필드 추가
- 특정 조건에서 필드를 포함/제외하고 싶을 때
요약: Go에서 커스텀 JSON 직렬화는 `json.Marshaler` 인터페이스의 `MarshalJSON()` 메서드 구현을 통해 가능하며, 이를 활용해 JSON 출력 형식을 완벽하게 제어할 수 있습니다.
Go의 JSON 직렬화는 기본적으로 구조체의 필드 이름을 JSON 키로 사용하지만, 커스텀 직렬화를 통해 더 복잡한 요구사항을 충족할 수 있습니다.
1. 기본 JSON 직렬화 Go에서 구조체를 JSON으로 직렬화하려면 `json.Marshal` 함수를 사용합니다.
기본적인 예시는 다음과 같습니다: ```go package main import ( "encoding/json" "fmt" ) type Person struct { Name string `json:"name"` Age int `json:"age"` } func main() { p := Person{Name: "Alice", Age: 30} jsonData, err := json.Marshal(p) if err != nil { fmt.Println(err) } fmt.Println(string(jsonData)) // {"name":"Alice","age":30} } ```
2. 커스텀 JSON 직렬화 커스텀 직렬화를 위해서는 `json.Marshaler` 인터페이스를 구현해야 합니다.
이 인터페이스는 `MarshalJSON` 메서드를 정의해야 하며, 이 메서드 내에서 원하는 형식으로 JSON을 생성할 수 있습니다.
예제: 커스텀 직렬화 다음은 `Person` 구조체를 커스텀 직렬화하는 예제입니다.
여기서는 `Age` 필드를 JSON에 포함하지 않고, `Name` 필드를 대문자로 변환하여 직렬화합니다.
```go package main import ( "encoding/json" "fmt" "strings" ) type Person struct { Name string Age int } // MarshalJSON 메서드를 구현하여 커스텀 직렬화를 정의합니다.
func (p Person) MarshalJSON() ([]byte, error) { type Alias Person // Alias를 사용하여 무한 루프를 방지합니다.
return json.Marshal(&struct { Name string `json:"name"` // Age 필드는 포함하지 않음 }{ Name: strings.ToUpper(p.Name), // 이름을 대문자로 변환 }) } func main() { p := Person{Name: "Alice", Age: 30} jsonData, err := json.Marshal(p) if err != nil { fmt.Println(err) } fmt.Println(string(jsonData)) // {"name":"ALICE"} } ```
3. 커스텀 JSON 역직렬화 역직렬화(디코딩)도 커스텀 방식으로 구현할 수 있습니다.
이를 위해 `json.Unmarshaler` 인터페이스를 구현하고 `UnmarshalJSON` 메서드를 정의합니다.
예제: 커스텀 역직렬화 다음은 JSON 데이터를 `Person` 구조체로 역직렬화하는 예제입니다.
여기서는 JSON의 `name` 필드를 소문자로 변환하여 저장합니다.
```go package main import ( "encoding/json" "fmt" "strings" ) type Person struct { Name string Age int } // UnmarshalJSON 메서드를 구현하여 커스텀 역직렬화를 정의합니다.
func (p *Person) UnmarshalJSON(data []byte) error { type Alias Person // Alias를 사용하여 무한 루프를 방지합니다.
aux := &struct { Name string `json:"name"` Age int `json:"age"` }{ Age: 0, // 기본값 설정 } if err := json.Unmarshal(data, &aux); err != nil { return err } p.Name = strings.ToLower(aux.Name) // 이름을 소문자로 변환 p.Age = aux.Age return nil } func main() { jsonData := []byte(`{"name":"ALICE","age":30}`) var p Person if err := json.Unmarshal(jsonData, &p); err != nil { fmt.Println(err) } fmt.Println(p) // {alice 30} } ```
4. Go에서 커스텀 JSON 직렬화 및 역직렬화는 `json.Marshaler`와 `json.Unmarshaler` 인터페이스를 구현함으로써 가능합니다.
이를 통해 JSON 데이터의 형식을 자유롭게 조정할 수 있으며, 특정 요구사항에 맞게 데이터를 변환할 수 있습니다.
이러한 기능은 API와의 상호작용이나 데이터 저장 시 매우 유용하게 사용될 수 있습니다.
작성자:
정주영 [비회원]
| 작성일자: 1년 전
2024-09-19 01:50:43
조회수: 145 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
조회수: 145 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.