4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gqlgen + Gorm でUint型の場合エラーになる

Posted at

今回のお題

gqlgen + Gorm を使った時にUint型のカラム値を返却する時に、型エラーが発生しうまくデータ取得できなかったので、その解消方法を記載します。

定義したモデルの構造体

db_model.go
package db_model

import (
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"time"
)

type User struct {
	ID        uint32    `gorm:"primary_key;AUTO_INCREMENT;"`
	Name      string    `gorm:"size:255"`
	Password  string    `gorm:"size:255"`
	Email     string    `gorm:"size:255"`
	CreatedAt time.Time `gorm:"column:created_at;type:datetime;"`
	UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;"`
	Items     []Item    `gorm:"foreignkey:ID"`
}

type Item struct {
	ID        uint32 `gorm:"primary_key;AUTO_INCREMENT;"`
	Name      string
	UserID    uint32
	CreatedAt time.Time `gorm:"column:created_at;type:datetime;"`
	UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;"`
}

これを元にGormのAutoMigrateを実行してテーブル作成します。

自前スカラーの定義

gqlgenはUint系の型をサポートしていないので、自前でスカラーを準備する必要があります。
調べていたら、すでに対応されている素晴らしい方でいたのでそれを拝借させて頂きました。

graph/model/uint.go
package model

import (
	"encoding/json"
	"fmt"
	"io"
	"strconv"

	"github.com/99designs/gqlgen/graphql"
)

func MarshalUint(t uint) graphql.Marshaler {
	return MarshalUint64(uint64(t))
}

func UnmarshalUint(v interface{}) (uint, error) {
	i, err := UnmarshalUint64(v)
	return uint(i), err
}

func MarshalUint64(t uint64) graphql.Marshaler {
	return graphql.WriterFunc(func(w io.Writer) {
		_, err := io.WriteString(w, strconv.FormatUint(t, 10))
		if err != nil {
			return
		}
	})
}

func UnmarshalUint64(v interface{}) (uint64, error) {
	switch t := v.(type) {
	case string:
		return strconv.ParseUint(t, 10, 64)
	case int:
		return uint64(t), nil
	case int64:
		return uint64(t), nil
	case json.Number:
		i, err := t.Int64()
		return uint64(i), err
	case float64:
		return uint64(t), nil
	}

	return 0, fmt.Errorf("unable to unmarshal uint64: %#v %T", v, v)
}

func MarshalUint32(t uint32) graphql.Marshaler {
	return graphql.WriterFunc(func(w io.Writer) {
		_, err := io.WriteString(w, strconv.FormatUint(uint64(t), 10))
		if err != nil {
			return
		}
	})
}

func UnmarshalUint32(v interface{}) (uint32, error) {
	switch t := v.(type) {
	case string:
		u, err := strconv.ParseUint(t, 10, 32)
		return uint32(u), err
	case int:
		return uint32(t), nil
	case int64:
		return uint32(t), nil
	case json.Number:
		i, err := t.Int64()
		return uint32(i), err
	case float64:
		return uint32(t), nil
	}

	return 0, fmt.Errorf("unable to unmarshal uint32: %#v %T", v, v)
}

gqlgen.yml

追加したスカラーを定義する

gqlgen.yml
...略
models:
  ID:
    model:
      - github.com/99designs/gqlgen/graphql.ID
      - github.com/99designs/gqlgen/graphql.Int
      - github.com/99designs/gqlgen/graphql.Int64
      - github.com/99designs/gqlgen/graphql.Int32
  Int:
    model:
      - github.com/99designs/gqlgen/graphql.Int
      - github.com/99designs/gqlgen/graphql.Int64
      - github.com/99designs/gqlgen/graphql.Int32
  User:
    model: "github.com/bb3104/gqlgen_gorm_sample/db_model.User"
  Item:
    model: "github.com/bb3104/gqlgen_gorm_sample/db_model.Item"
-------- ここから追加 ---------
  Uint:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint"
  Uint32:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint32"
  Uint64:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint64"

grahpqlのスキーマ構造

graph/schema.graphqls
type User {
  id: Uint32! <- 最初はここにID!を定義してた為、Graphqlクエリのレスポンス結果がエラーになった。
  name: String!
  password: String!
  email: String!
  items: [Item!]
  createdAt: Time!
  updatedAt: Time!
}

type Item {
  id: Uint32!
  name: String!
  createdAt: Time!
  updatedAt: Time!
}

type Query {
  users: [User!]!
}

scalar Time
scalar Uint32 <- 追加

これでGormで作成したIDカラムの型とスキーマ構造で定義したIDの型がイコールになって、無事解決!!

上記内容はgithubにソースコードがありますので、よかったらぜひご覧になってみてください。
https://github.com/bb3104/gqlgen_gorm_sample

参考にしたサイト

https://gist.github.com/JonLundy/ad750704b83aebec69749f98ba48dcdc
https://github.com/99designs/gqlgen
https://gorm.io/ja_JP/docs/index.html

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?