我如何基于类型json.Unmarshal

时间:2014-01-06 01:05:21

标签: go

我正在为Flowdock API编写一个go客户端。他们的Message for Message有许多属性,其中两个是EventContent

Event = message时,Content是一个字符串。当Event = comment Content是JSON对象时。

我想在需要之前推迟联合Content。为此,我在我的结构中映射RawContent并在Content()上定义Message方法以返回正确的对象。

以下是代码说明:

package main

import (
    "fmt"
    "encoding/json"
)

// Message represents a Flowdock chat message.
type Message struct {
    Event            *string          `json:"event,omitempty"`
    RawContent       *json.RawMessage `json:"content,omitempty"`
}


func (m *Message) Content() (content interface{}) {
    // when m.Event is a message the RawContent is a string
    // real code handles unmarshaling other types (removed for this example)
    return string(*m.RawContent)
}

func main() {
    var message = &Message{}
    rawJSON := `{"event": "message", "content": "Howdy-Doo @Jackie #awesome"}`
    if err := json.Unmarshal([]byte(rawJSON), &message); err != nil {
        panic(err.Error())
    }

    event := "message"
    rawMessage := json.RawMessage("Howdy-Doo @Jackie #awesome")
    want := &Message{
        Event: &event,
        RawContent: &rawMessage,
    }

    fmt.Println(message.Content(), want.Content())
}

运行此结果的结果是:http://play.golang.org/p/eds_AA6Aay

"Howdy-Doo @Jackie #awesome" Howdy-Doo @Jackie #awesome

注意:message.Content()和want.Content()是不同的!

起初我没想到引号会被包含在消息中,但是由于JSON的解析方式,它才有意义。它只是整个rawJSON字符串的一部分。

所以我的问题是:

  1. 我应该剥掉报价吗?
  2. 如果是这样,Go去剥离的最简单方法是什么?也许这个:http://play.golang.org/p/kn8XKOqF0z行(6,19)?
  3. 这是处理JSON的正确方法,它可以为同一属性提供不同的类型吗?
  4. 以下是一个更完整的示例,展示了我如何处理JSON RawContenthttp://play.golang.org/p/vrBJ5RYcql

1 个答案:

答案 0 :(得分:3)

问题1:

不,你应该json.Unmarshal内容也只包含一个字符串。除了引号之外,JSON字符串还可能包含反斜杠转义的控制字符。

问题2:

由于问题1中的答案,请对“消息”案例执行以下操作:

var s string        
if err := json.Unmarshal([]byte(*m.RawContent), &s); err != nil {
    panic(err)
}
return s

问题3:

这是解组事件类型字符串并使用RawMessage存储JSON其余部分的好方法,直到您评估了类型并知道内容具有何种结构。

您可能还想考虑具有特定类型的简单字符串内容,例如:

type MessageContent string

通过这种方式,您可以自由地在类型上实现方法,允许Content方法返回除空接口{}之外的其他接口。

注意:

请注意,如果您还按照我的建议对json.Unmarshal消息字符串进行解组,那么当您尝试解组未引用的want.RawContent字符串时,您的Playground示例会发生混乱,因为它不是有效的JSON。