在我的Go代码中,我有以下情况:
type Operator int
const (
UNKNOWN Operator = iota
EQUALS
CONTAINS
BETWEEN
DISTANCE
)
type Filter struct {
Field string `json:"field"`
Operator Operator `json:"operator"`
Values []string `json:"values"`
}我期望的JSON如下所示:
{
"operator": "EQUALS",
"field": "name",
"values": [ "John", "Doe" ]
}我能否创建一个映射,以便json.Unmarshal将在过滤器结构中设置正确的运算符常量?我知道解编组器接口,但我不认为它真的可以用在一个常量值上。
我真的很想将常量保留在go代码中,因为这很好地增强了类型检查和一致性。
发布于 2014-02-06 18:13:15
encoding/json Unmarshaler接口将与Operator类型一起工作,但它必须有一个指针作为接收方:
func (o *Operator) UnmarshalJSON(b []byte) error {
str := strings.Trim(string(b), `"`)
switch {
case str == "CONTAINS":
*o = CONTAINS
default:
*o = UNKNOWN
// or return an error...
}
return nil
}JSON解码器将从Operator结构中获取Filter字段的地址,并在其上调用UnmarshalJSON方法。
请注意,您可以通过将上面的encoding/TextUnmarshaler更改为UnmarshalText来实现更通用的UnmarshalText。
下面是一个游乐场示例:http://play.golang.org/p/szcnC6L86u
可以说,为操作符使用字符串基类型可能更简单:http://play.golang.org/p/FCCg1NOeYw。
发布于 2014-02-06 17:54:17
您可以将对象包装在解编组器中。例:
package main
import (
"encoding/json"
"fmt"
)
type Operator int
const (
UNKNOWN Operator = iota
EQUALS
CONTAINS
BETWEEN
DISTANCE
)
type Filter struct {
Field string `json:"field"`
RawOperator string `json:"operator"`
Operator Operator `json:"-"`
Values []string `json:"values"`
}
type FilterUnmarshaler struct {
Filter
}
func (f *FilterUnmarshaler) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &f.Filter); err != nil {
return err
}
switch f.RawOperator {
case "UNKOWN":
f.Operator = UNKNOWN
case "EQUALS":
f.Operator = EQUALS
case "CONTAINS":
f.Operator = CONTAINS
case "BETWEEN":
f.Operator = BETWEEN
case "DISTANCE":
f.Operator = DISTANCE
default:
return fmt.Errorf("Unkown operator %s", f.RawOperator)
}
return nil
}
func main() {
rawJson := []byte(`
{
"operator": "BETWEEN",
"field": "name",
"values": [ "John", "Doe" ]
}
`)
val := &FilterUnmarshaler{}
if err := json.Unmarshal(rawJson, val); err != nil {
panic(err)
}
fmt.Printf("%#v\n", val)
}不使用包装器,我就找不到如何不陷入无限递归。
这个示例展示了如何解除封送,但您很可能也希望将其应用于Marshal,以便使用整数运算符从对象中获得正确的带有运算符字符串的json。
您还可能希望创建一个映射而不是const。或者,创建一个映射并用您的const和它们的字符串等效来手动填充它。
https://stackoverflow.com/questions/21609363
复制相似问题