앞서 소개한 go-pg를 사용하면 json 데이터와 struct를 쉽게 맵핑할수 있었습니다 반면에 Grom은 직접적으로 맵핑이 불가능 하여 어려움이 있었습니다.

이번 글에서는 Gorm을 사용하여 데이터를 체계적으로 관리하기 위하여 json 데이터를 맵핑 하는 방법에 대하여 기술해 보겠습니다.

구조체 선언

type User struct {
gorm.Model
Name string
Todos json.RawMessage `gorm:"type:jsonb;"`
Todo []Todo `gorm:"-"`
}

type Todo struct {
Todo string
Priority int64
}

기본적으로 Gorm에서 Postgres의 Jsonb 타입을 사용하기 위해서는*json.RawMessage(= postgres.Jsonb)* 을 사용하여 해당 값이 json 데이터임을 선언해 줍니다.이 후 gorm 태그를 사용하여 해당 컬럼이 jsonb 타입임을 알려줍니다

users라는 하나의 테이블에서 nested 구조로 todo list를 같이 관리한다고 하였을때, 위에서 선언한 컬럼의 데이터를 모델에 바인딩하여 사용하기 위하여 gorm태그로 무시되는 Todo 배열을 추가해 줍니다.

json.RawMessage 데이터 맵핑(디코딩)

json으로 입력받은 json.RawMessage 데이터를 모델에 맵핑하기 위하여 json.Unmarshal 함수를 사용하여 Todos로 들어온 데이터를 Todo 로 맵핑해줍니다.

func (u *User) UnmarshalTodoData() error {
return json.Unmarshal(u.Todos, &u.Todo)
}

맵핑 이후에는 다음과 같이 Todo로 접근하여 데이터를 관리할 수 있습니다.

...
user.Todo[0].Todo = "Edited"
user.Todo[0].Priority = 1
...

json.RawMessage로 변환(인코딩)

위의 과정을 진행하고 실제로 데이터베이스에 적용하기 위해서는 다시 json.Marshal을 사용하여 json.RawMessage로 변환하는 과정을 거쳐 user.Todos값을 변경 해주어야 합니다.

func (u *User) MarshalTodoData() error {
var err error
u.Todos, err = json.Marshal(u.Todo)
return err
}

위와 같은 과정을 통하여 json.Todos에 값을 할당함으로서 gorm의 jsonb 타입의 자료를 구조체에 할당 하여 관리 할 수 있습니다.

요약