我如何解组JSON?

时间:2014-05-22 05:13:49

标签: json go

我还在学习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。

这是我走了多远。但我被困在这里。

http://play.golang.org/p/YzrhjuXxGN

3 个答案:

答案 0 :(得分:11)

这是去做的方式 - 不需要反思。为其创建新类型RawString并创建MarshalJSONUnmarshalJSON方法。 (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)
}