2014-01-06 26 views
2

我正在爲Flowdock API編寫一個go客戶端。它們對消息API具有多個屬性的其中兩個是EventContent如何基於類型的json.Unmarshal

Event = message然後Content是一個字符串。當Event = commentContent是一個JSON對象。

我想推遲undemarhsalling Content,直到它需要。爲此,我在我的結構中映射RawContent並在Message上定義Content()方法以返回正確的對象。

下面是代碼來說明:

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. 如果是這樣的話,最簡單的方法是去脫衣舞?也許這個:http://play.golang.org/p/kn8XKOqF0z行(6,19)?
  3. 這是甚至正確的方法來處理JSON,可以有不同類型的相同的屬性?

下面是一個更完整的例子展示我如何處理JSON RawContenthttp://play.golang.org/p/vrBJ5RYcql

回答

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的其餘部分,直到您評估了類型並知道內容的類型t已經。

您可能還想考慮具有特定的類型也適用於簡單的字符串內容,例如。:

type MessageContent string 

這種方式,你可以自由地落實該類型的方法,使內容方法返回一些其他的接口不僅僅是空接口{}。

注:

要注意的是,如果你還json.Unmarshal消息字符串,我建議,試圖解編你的非上市want.RawContent字符串時,你的遊樂場例子會產生恐慌,因爲它是不有效的JSON。

+0

感謝您的答案。我曾試過你的答案2之前,但問題是該字符串是無效的JSON,所以它不能被解組。這裏是一個例子http://play.golang.org/p/I5MBnMEpC5。 – Will

+0

這是我注意* Note *的地方;您的原始'rawJSON'是正確的JSON,並且將它解組到'Message'結構中會將'RawContent'設置爲正確的JSON字符串。但是放入'rawMessage'中的非引號字符串不是JSON,因此它在Unmarshalled時會產生一個錯誤。看到這[Playground](http://play.golang.org/p/HRtN4iJnZT) – ANisus

+0

噢!所以我感到恐慌,但認爲這是因爲某種原因不想要的信息 - 非常感謝 – Will