Json数据适配器

时间:2014-03-19 21:08:36

标签: go

我想在

中使用JSON
{ name: "http://example.com", ...}

并将其映射到

{ url: "http://example.com", ...}

我想做这个映射,并能够作为Url回到json。结构相当大,所以可以用一个结构来创建多个结构类型吗?

这是我到目前为止所采用的解决方案:http://play.golang.org/p/wBPbSjkTYF

在看到答案以及我未能准确描述我的用例之后。更新到我试图做的实际映射:

{ "data": { "name": "http://example.com", "key": "value" } }

要:

{ "url": "http://example.com", { "data": "key": "value" } }

2 个答案:

答案 0 :(得分:1)

json包没有任何标签可以让您在Marshal上使用一个字段的键名,在Unmarshal上使用不同的字符。

仍然可以以不同的方式对结构进行制作,但为了做到这一点,你必须实现自己的Marshaller(MarshalJSON函数)。一个工作的例子:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type Data struct {
    Url string `json:"name"`
}

// marshalObject takes a slice of key values
// (should be correctly escaped json strings without "")
// and another slice of interface{} values and marshals
// them into a JSON object string
func marshalObject(keys []string, values []interface{}) ([]byte, error) {

    if len(keys) != len(values) {
        panic("Different length of keys and values slices")
    }

    if len(keys) == 0 {
        return []byte(`{}`), nil
    }

    var b bytes.Buffer
    b.Write([]byte(`{"`))

    for i, key := range keys {
        if i != 0 {
            b.Write([]byte(`,"`))
        }
        b.WriteString(key)
        b.Write([]byte(`":`))
        j, err := json.Marshal(values[i])
        if err != nil {
            return nil, err
        }
        b.Write(j)
    }

    b.Write([]byte(`}`))

    return b.Bytes(), nil
}

func (d *Data) MarshalJSON() ([]byte, error) {
    // Here you can add a list of keys and values.
    // Currently it is only `url` mapped to d.Url
    return marshalObject(
        []string{
            `url`,
        },
        []interface{}{
            d.Url,
        },
    )
}

func main() {
    i := []byte(`{"name":"http://example.com"}`)
    fmt.Printf("Json Input: %+s\n", i)

    var d *Data
    err := json.Unmarshal(i, &d)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Data: %#v\n", d)

    o, err := json.Marshal(d)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Json Output: %+s\n", o)

}

<强>结果:

Json Input: {"name":"http://example.com"}
Data: &main.Data{Url:"http://example.com"}
Json Output: {"url":"http://example.com"}

<强>游乐场:

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

答案 1 :(得分:0)

如果您将JSON对象解组为map[string]interface{}变量,您将获得对象中的所有内容,而不仅仅是几个字段。进行必要的修改应该是相当直接的,如下所示:

func nameToUrl(data []byte) ([]byte, error) {
    var obj map[string]interface{}
    if err := json.Unmarshal(data, &obj); err != nil {
        return nil, err
    }
    if name, ok := obj["name"]; ok {
        delete(obj, "name")
        obj["url"] = name
    }
    return json.Marshal(obj)
}

您可以在此处进行试验:http://play.golang.org/p/0jz_HAGg3E