文字列型を作成して、非マーシャリング中に複数回割り当てられている場合はエラーを返すことができます。 json.Decoder
でこれを処理する
type singleAssignString string
func (s *singleAssignString) UnmarshalJSON(b []byte) error {
if s != nil && *s != "" {
return fmt.Errorf("multiple string assignment")
}
*s = singleAssignString(string(b))
return nil
}
https://play.golang.org/p/v4L1EjTESX
適切にすべてのフィールドを取得し、優れたエラーメッセージを返すための唯一の方法におそらくあります。これは、外部型のUnmarshalJSONメソッドの組み込みデコーダで行うことができます。ラフの例では、次のようになります。
type Data struct {
Name string
}
func (d *Data) UnmarshalJSON(b []byte) error {
dec := json.NewDecoder(bytes.NewReader(b))
key := ""
value := ""
for dec.More() {
tok, err := dec.Token()
if err != nil {
return err
}
s, ok := tok.(string)
if !ok {
continue
}
switch {
case key == "":
key = s
continue
case value == "":
value = s
}
if key == "Name" {
if d.Name != "" {
return fmt.Errorf("multiple assignment to Name")
}
d.Name = s
}
key = ""
}
return nil
}
最初のアプローチとの深刻な問題はunmarshalerは、それが中にエラーを検出し、コンテキストのないアイデアを持っていないということであるあなたは、エラーメッセージにフィールドの名前を焼いたが、あなたが必要とする必要があります。たとえば、オブジェクトのすべてのフィールドをチェックすることは実用的ではありません(各フィールドの値のカスタムタイプを定義することができません)。だから、私は2番目の投票に投票します。間違いなく複雑ですが、エラーが検出されると、その値ではなく、問題のキーですぐに検出されます。 – kostix
@kostix:私は同意します。外側のstruct構造体に独自の 'UnmarshlJSON'を実装し、そこで非整列化を行い、' UnmarshalFieldError'や他のより有益なメッセージを返すことで、これを軽減できます。しかし、はい、私は唯一の "適切な"方法は、各トークンの復号化を個別に処理することだと思います。 – JimB