如何解组 JSON?
Posted
技术标签:
【中文标题】如何解组 JSON?【英文标题】:How do I Unmarshal JSON? 【发布时间】:2014-05-22 05:13:48 【问题描述】:我正在尝试将 JSON 解组为一个结构。但是,该结构有一个带有标签的字段。使用反射,我尝试查看标签中是否包含字符串“json”。如果是这样,那么要解组的 json 应该简单地作为字符串解组到字段中。
例子:
const data = `"I":3, "S":"phone": "sales": "2223334444"`
type A struct
I int64
S string `sql:"type:json"`
问题很简单 - 将 json 中的“S”作为字符串解组到结构 A 中。
这就是我已经走了多远。但是我被困在这里了。
http://play.golang.org/p/YzrhjuXxGN
【问题讨论】:
【参考方案1】:这是最好的方法 - 不需要反射。创建一个新类型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的实现来创建上面的。
【讨论】:
【参考方案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 := A
_ = json.Unmarshal([]byte(data), &msg)
data, _ := json.Marshal(msg.Sjson)
msg.S = string(data)
fmt.Println("Done", msg)
【讨论】:
【参考方案3】:看起来问题是您的代码中的s interface
不可寻址。对于Value.SetString
,值必须是可寻址的,并且带有Kind
字符串。你可以查看它的文档 - http://golang.org/pkg/reflect/#Value.SetString
我如何理解SetString
不会更改a
中的值,因为您只使用接口s
。在Laws of Reflection 中,您可以找到“reflect.ValueOf 是 x 的副本,而不是 x 本身”(第三定律)。
为了使您的代码正常工作,我做了一些类型断言,并在指向断言结构的指针上使用了reflect.ValueOf
。
要检查 Value
是否可设置或可寻址,您可以使用 Value.CanSet
广告 Value.CanAddr
工作代码:http://play.golang.org/p/DTriENkzA8
不知道这样做是否正确
【讨论】:
谢谢。但是如果没有类型断言,我们如何做到这一点。我们通常不知道 UnmarshalJsonIntoStruct 函数中的类型(s = l.(A)) @BVSat 你可以为所有可能的结构做一个开关/案例以上是关于如何解组 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Akka HTTP 中将“text/plain”解组为 JSON