简体   繁体   English

转到json是不好的做法。将json对象解码为空接口?

[英]Is it bad practice in Go to json.Decode a json object to an empty interface?

I have a fairly large nested JSON object I want to decode. 我有一个相当大的嵌套JSON对象我想要解码。 I could decode this to a well defined nested struct, but an alternate solution I've seen is to just decode it to an empty interface. 我可以将其解码为定义良好的嵌套结构,但我看到的另一种解决方案是将其解码为空接口。

Functionally, this works fine. 从功能上来说,这很好。 But I'm wondering if behind the scenes I'm incurring a performance penalty (reflecting) when I decode the object from JSON and again when I later marshal it to JSON. 但我想知道,当我从JSON解码对象时,以及当我稍后将其编组为JSON时,我是否会在幕后产生性能损失(反映)。

Thoughts? 思考? Thanks in advance. 提前致谢。

Code: 码:

CustomizationData    interface{} `json:"customizationData" datastore:"-"`

vs.

CustomizationData    struct {
    Items []struct {
        ID     string `json:"id"`
        Images []struct {
            CustomizationState struct {
                Areas []struct {
                    Height float64 `json:"height"`
                    ID     string  `json:"id"`
                    Left   float64 `json:"left"`
                    Parent struct {
                        Height float64 `json:"height"`
                        Left   float64 `json:"left"`
                        Top    float64 `json:"top"`
                        Width  float64 `json:"width"`
                    } `json:"parent"`
                    Rotation float64 `json:"rotation"`
                    Text     string  `json:"text"`
                    Top      float64 `json:"top"`
                    URL      string  `json:"url"`
                    Width    float64 `json:"width"`
                } `json:"areas"`
                BackgroundColor string  `json:"backgroundColor"`
                IsUserSet       bool    `json:"isUserSet"`
                Orientation     float64 `json:"orientation"`
            } `json:"customizationState"`
            SpaceId string `json:"spaceId"`
        } `json:"images"`
        ProductId    float64 `json:"productId"`
        Quantity     float64 `json:"quantity"`
        Sku          string  `json:"sku"`
        TemplateName string  `json:"templateName"`
    } `json:"items"`
    ShippingAddress struct {
        City        string `json:"city"`
        CountryCode string `json:"countryCode"`
        Email       string `json:"email"`
        FirstName   string `json:"firstName"`
        LastName    string `json:"lastName"`
        Line1       string `json:"line1"`
        Phone       string `json:"phone"`
        PostalCode  string `json:"postalCode"`
        State       string `json:"state"`
    } `json:"shippingAddress"`
    TimeStamp string `json:"timeStamp"`
} `json:"customizationData" datastore:"-"

And potentially more. 还有更多。

It depends entirely on what you intend on doing with the Unmarshalled data. 这完全取决于您打算如何处理Unmarshalled数据。

If you have nested objects / arrays in your json data, then you will end up with nested interfaces. 如果在json数据中嵌套了对象/数组,那么最终将使用嵌套接口。 That means you need to explicitly convert your interfaces to the correct type to access their data. 这意味着您需要将接口显式转换为正确的类型以访问其数据。 In that case you are far better off using the struct in the second example as you will have your data more easily accessible as in myData.Items[0].CustomizationState.Areas[0].Height . 在这种情况下,您最好在第二个示例中使用结构,因为您将更容易访问您的数据,如myData.Items[0].CustomizationState.Areas[0].Height Doing that with nested interface conversion is going to be a pain. 使用嵌套接口转换执行此操作将是一件痛苦的事。

On the other hand, if you are just outputting this data, for example as a response to a webservice call, then you don't need to know the structure and can just spit it back out. 另一方面,如果您只是输出此数据,例如作为对Web服务调用的响应,那么您不需要知道结构,只需将其吐出即可。

Personally, I always use the latter. 就个人而言,我总是使用后者。

I assume you are using the awesome service at http://mervine.net/json2struct to convert your json into usable Go structs. 我假设您正在使用http://mervine.net/json2struct上的强大服务将您的json转换为可用的Go结构。

Here is a link showing the difference in ease of access between the two methods. 这是一个链接,显示两种方法之间的访问容易程度的差异。 http://play.golang.org/p/OlJJPZcxT7 http://play.golang.org/p/OlJJPZcxT7

And for those who want to stay in-page: 对于那些想留在页面内的人:

var dataz = `{"foo": ["bar", "baz"], "boff": {"foo": "bar", "baz": "boff"}}`

type Dataz struct {
    Foo  []string `json:"foo"`
    Boff struct {
        Foo string `json:"foo"`
        Baz string `json:"baz"`
    } `json:"boff"`
}

func main() {
    // Method 1
    var d interface{}
    json.Unmarshal([]byte(dataz), &d)
    fmt.Println(d.(map[string]interface{})["foo"].([]interface{})[0])

    // Method 2
    var D Dataz
    json.Unmarshal([]byte(dataz), &D)
    fmt.Println(D.Foo[0])
}

EDIT 编辑
Edit based on comment about performance 根据有关性能的评论进行编辑

Thankfully we can test it with built-in Go tools 值得庆幸的是,我们可以使用内置的Go工具进行测试

> go test -bench .
testing: warning: no tests to run
PASS
BenchmarkInterface    300000          6208 ns/op
BenchmarkStruct       500000          3622 ns/op
ok      parse   3.773s

It's the difference between handling unmarshalling of 276,000/sec or 161,000/sec. 这是处理276,000 /秒或161,000 /秒的解组之间的区别。 So this will almost certainly not be your bottleneck. 所以这几乎肯定不是你的瓶颈。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM