无法在gqlgen中生成标量JSON。

huangapple go评论90阅读模式
英文:

Can't generate scalar JSON in gqlgen

问题

我有一个 GQL 方案:

extend type MyType @key(fields: "id") {
  id: ID! @external
  properties: JSON @external
  myField: String! @requires(fields: "properties")
}
scalar JSON

在 graph/model/model.go 中:

package model

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

type JSON map[string]interface{}

// UnmarshalGQL 实现了 graphql.Unmarshaler 接口
func (b *JSON) UnmarshalGQL(v interface{}) error {
	*b = make(map[string]interface{})
	byteData, err := json.Marshal(v)
	if err != nil {
		panic("FAIL WHILE MARSHAL SCHEME")
	}
	tmp := make(map[string]interface{})
	err = json.Unmarshal(byteData, &tmp)
	if err != nil {
		panic("FAIL WHILE UNMARSHAL SCHEME")
		//return fmt.Errorf("%v", err)
	}
	*b = tmp
	return nil
}

// MarshalGQL 实现了 graphql.Marshaler 接口
func (b JSON) MarshalGQL(w io.Writer) {
	byteData, err := json.Marshal(b)
	if err != nil {
		panic("FAIL WHILE MARSHAL SCHEME")
	}
	_, _ = w.Write(byteData)
}

但是当我运行 go run github.com/99designs/gqlgen generate 时出现错误:

generating core failed: type.gotpl: template: type.gotpl:52:28: executing "type.gotpl" at <$type.Elem.GO>: nil pointer evaluating *config.TypeReference.
GOexit status 1

我只需要获取名为 JSON 的 map[string]interface{}。我知道有一个标量类型 Map,但是对于 Apollo Federation,该字段必须称为 JSON。

英文:

I have a GQL scheme:

extend type MyType @key(fields: &quot;id&quot;) {
  id: ID! @external
  properties: JSON @external
  myField: String! @requires(fields: &quot;properties&quot;)
}
scalar JSON

In graph/model/model.go:

package model

import (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;strconv&quot;
	&quot;strings&quot;
)

type JSON map[string]interface{}

// UnmarshalGQL implements the graphql.Unmarshaler interface
func (b *JSON) UnmarshalGQL(v interface{}) error {
	*b = make(map[string]interface{})
	byteData, err := json.Marshal(v)
	if err != nil {
		panic(&quot;FAIL WHILE MARSHAL SCHEME&quot;)
	}
	tmp := make(map[string]interface{})
	err = json.Unmarshal(byteData, &amp;tmp)
	if err != nil {
		panic(&quot;FAIL WHILE UNMARSHAL SCHEME&quot;)
		//return fmt.Errorf(&quot;%v&quot;, err)
	}
	*b = tmp
	return nil
}

// MarshalGQL implements the graphql.Marshaler interface
func (b JSON) MarshalGQL(w io.Writer) {
	byteData, err := json.Marshal(b)
	if err != nil {
		panic(&quot;FAIL WHILE MARSHAL SCHEME&quot;)
	}
	_, _ = w.Write(byteData)
}

But when I run go run github.com/99designs/gqlgen generate
error:

generating core failed: type.gotpl: template: type.gotpl:52:28: executing &quot;type.gotpl&quot; at &lt;$type.Elem.GO&gt;: nil pointer evaluating *config.TypeReference.
GOexit status 1

I just need to get map[string]interface{} which called JSON. I knew there's scalar Map, but for apollo federation that field must be called JSON.

答案1

得分: 2

应该将MarshalGQL替换为MarshalJSON,如下所示:

type JSON map[string]interface{}

func MarshalJSON(b JSON) graphql.Marshaler {
	return graphql.WriterFunc(func(w io.Writer) {
		byteData, err := json.Marshal(b)
		if err != nil {
			log.Printf("在编组JSON时失败:%v\n", string(byteData))
		}
		_, err = w.Write(byteData)
		if err != nil {
			log.Printf("在写入数据时失败:%v\n", string(byteData))
		}
	})
}

func UnmarshalJSON(v interface{}) (JSON, error) {
	byteData, err := json.Marshal(v)
	if err != nil {
		return JSON{}, fmt.Errorf("在编组方案时失败")
	}
	tmp := make(map[string]interface{})
	err = json.Unmarshal(byteData, &tmp)
	if err != nil {
		return JSON{}, fmt.Errorf("在解组方案时失败")
	}
	return tmp, nil
}

希望对你有帮助!

英文:

it's should to replace MarshalGQL to MarshalJSON like:

type JSON map[string]interface{}

func MarshalJSON(b JSON) graphql.Marshaler {
	return graphql.WriterFunc(func(w io.Writer) {
		byteData, err := json.Marshal(b)
		if err != nil {
			log.Printf(&quot;FAIL WHILE MARSHAL JSON %v\n&quot;, string(byteData))
		}
		_, err = w.Write(byteData)
		if err != nil {
			log.Printf(&quot;FAIL WHILE WRITE DATA %v\n&quot;, string(byteData))
		}
	})
}

func UnmarshalJSON(v interface{}) (JSON, error) {
	byteData, err := json.Marshal(v)
	if err != nil {
		return JSON{}, fmt.Errorf(&quot;FAIL WHILE MARSHAL SCHEME&quot;)
	}
	tmp := make(map[string]interface{})
	err = json.Unmarshal(byteData, &amp;tmp)
	if err != nil {
		return JSON{}, fmt.Errorf(&quot;FAIL WHILE UNMARSHAL SCHEME&quot;)
	}
	return tmp, nil
}

huangapple
  • 本文由 发表于 2022年2月2日 20:54:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/70955985.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定