我还在学习Go。我试图将json解组成结构。但是,struct有一个带标记的字段。使用反射,我试着看看标签是否有字符串" json"在里面。如果确实如此,那么json to unmarshal应该只是作为一个字符串被解组到字段中。
示例:
const data = `{"I":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S string `sql:"type:json"`
}
问题很简单 - 解组" S"在json中作为字符串进入结构A。
这是我走了多远。但我被困在这里。
答案 0 :(得分:11)
这是去做的方式 - 不需要反思。为其创建新类型RawString
并创建MarshalJSON
和UnmarshalJSON
方法。 (playground)
// RawString is a raw encoded JSON object.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawString string
// MarshalJSON returns *m as the JSON encoding of m.
func (m *RawString) MarshalJSON() ([]byte, error) {
return []byte(*m), nil
}
// UnmarshalJSON sets *m to a copy of data.
func (m *RawString) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("RawString: UnmarshalJSON on nil pointer")
}
*m += RawString(data)
return nil
}
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S RawString `sql:"type:json"`
}
func main() {
a := A{}
err := json.Unmarshal([]byte(data), &a)
if err != nil {
log.Fatal("Unmarshal failed", err)
}
fmt.Println("Done", a)
}
我修改了RawMessage的实现以创建上述内容。
答案 1 :(得分:2)
看起来问题是代码中的s interface{}
无法寻址。对于Value.SetString
,Value必须是可寻址的,并使用Kind
字符串。你可以查看它的文档 - http://golang.org/pkg/reflect/#Value.SetString
我的理解SetString
不会更改a
中的值,因为您只使用接口s
。在Laws of Reflection中你可以找到“reflect.ValueOf是x的副本,而不是x本身”(第3定律)。
为了使你的代码工作,我做了一些类型的断言,并在指向断言结构的指针上使用了reflect.ValueOf
。
要检查Value
是否可设置或可寻址,您可以使用Value.CanSet
ad Value.CanAddr
工作代码:http://play.golang.org/p/DTriENkzA8
不知道这是否正确的方法
答案 2 :(得分:2)
这里的问题是你使用一种编码格式用于两种协议,可能你的模型有问题。
这是一个有效的Json有效负载,应该这样处理。您可以使用的一个技巧是创建 另一个字段来处理"字符串" json和一个处理" json结构"。 看到这个修改过的例子:我首先解组json然后编组回json来创建上传到数据库的最终字符串。一个字段用于解组,另一个字段用于与DB通信。
package main
import(
"fmt"
"encoding/json"
)
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
Sjson struct {
Phone struct {
Sales string `json:"sales"`
} `json:"phone"`
} `json:"S", sql:"-"`
S string `sql:"type:json",json:"-"`
}
func main() {
msg := new(A)
_ = json.Unmarshal([]byte(data), &msg)
data, _ := json.Marshal(msg.Sjson)
msg.S = string(data)
fmt.Println("Done", msg)
}