2017-10-15 125 views
0

我有一個第三方服務返回JSON,其中一個字段包含數據集合。這是它返回的結構的一個例子。Unmarshal JSON可能是一個字符串或對象

{ 
    "title": "Afghanistan", 
    "slug": "afghanistan", 
    "fields": { 
    "fieldOne": "", 
    "fieldTwo": { 
     "new1": { 
     "type": "contentBlock",, 
     "fields": { 
      "richTextBlick": "<p>This is the travel advice.<\/p>" 
     } 
     } 
    }, 
    "fieldThree": { 
     "new1": { 
     "type": "introBlock", 
     "fields": { 
      "text": "This is a title" 
      "richText": "<p>This is the current travel summary for Afganistan.<\/p>" 
     } 
     }, 
     "new2": { 
     "type": "contentBlock", 
     "fields": { 
      "richText": "<p>It has a second block of content!<\/p>" 
     } 
     } 
    }, 
    "fieldfour": "country" 
    } 
} 

每個「字段」條目可以是字符串或其他對象。我想將它們解碼成類似下面的結構。

type EntryVersion struct { 
    Slug string `json:"slug"` 
    Fields map[string][]EntryVersionBlock `json:"fields"` 
} 

type EntryVersionBlock struct { 
    Type string `json:"type"` 
    Fields map[string]string `json:"fields"` 
} 

如果字段值只是一個字符串,我會敷在與「文本」,並在字段映射單個條目類型的EntryVersionBlock。

任何想法如何以有效的方式做到這一點?我可能必須在極端的情況下做幾百次。

感謝

+1

嘗試使用這個庫https://github.com/tidwall/gjson – Radi

回答

3

你是結構法從JSON的一點點了。 FieldsEntryVersion是一個對象不是數組,因此使它成爲一個切片不是你想要的。我建議你把它改成這樣:

type EntryVersion struct { 
    Slug string      `json:"slug"` 
    Fields map[string]EntryVersionBlock `json:"fields"` 
} 

EntryVersionBlock沒有在相應的JSON一個"type"領域,它與字段名稱條目"new1""new2"等,所以我建議你添加一個第三類Entry解鎖這些領域。

type Entry struct { 
    Type string   `json:"type"` 
    Fields map[string]string `json:"fields"` 
} 

你會更新EntryVersionBlock看起來是這樣的:

type EntryVersionBlock struct { 
    Value string   `json:"-"` 
    Fields map[string]Entry `json:"fields"` 
} 

以及處理您原來的問題,你可以有EntryVersionBlock類型實現json.Unmarshaler界面,在檢查的第一個字節數據傳遞給UnmarshalJSON方法,如果它是雙引號,則它是一個字符串,如果它是一個捲曲的開頭括號,則它是一個對象。事情是這樣的:

func (evb *EntryVersionBlock) UnmarshalJSON(data []byte) error { 
    switch data[0] { 
    case '"': 
     if err := json.Unmarshal(data, &evb.Value); err != nil { 
      return err 
     } 
    case '{': 
     evb.Fields = make(map[string]Entry) 
     if err := json.Unmarshal(data, &evb.Fields); err != nil { 
      return err 
     } 
    } 
    return nil 
} 

遊樂場:https://play.golang.org/p/IsTXI5202m

相關問題