Skip to content

Instantly share code, notes, and snippets.

@md2k
Forked from mjohnsullivan/parse_json.go
Created March 14, 2018 15:05
Show Gist options
  • Save md2k/ec292658ac1923135c40f616cc78329b to your computer and use it in GitHub Desktop.
Save md2k/ec292658ac1923135c40f616cc78329b to your computer and use it in GitHub Desktop.

Revisions

  1. @mjohnsullivan mjohnsullivan created this gist Dec 14, 2015.
    85 changes: 85 additions & 0 deletions parse_json.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    // Parsing arbitrary JSON using interfaces in Go
    // Demonstrates how to parse JSON with abritrary key names
    // See https://blog.golang.org/json-and-go for more info on generic JSON parsing

    package main

    import (
    "encoding/json"
    "fmt"
    )

    var jsonBytes = []byte(`
    {
    "key1":{
    "Item1": "Value1",
    "Item2": 1},
    "key2":{
    "Item1": "Value2",
    "Item2": 2},
    "key3":{
    "Item1": "Value3",
    "Item2": 3}
    }`)

    // Item struct; we want to create these from the JSON above
    type Item struct {
    Item1 string
    Item2 int
    }

    // Implement the String interface for pretty printing Items
    func (i Item) String() string {
    return fmt.Sprintf("Item: %s, %d", i.Item1, i.Item2)
    }

    func main() {

    // Unmarshal using a generic interface
    var f interface{}
    err := json.Unmarshal(jsonBytes, &f)
    if err != nil {
    fmt.Println("Error parsing JSON: ", err)
    }

    // JSON object parses into a map with string keys
    itemsMap := f.(map[string]interface{})

    // Loop through the Items; we're not interested in the key, just the values
    for _, v := range itemsMap {
    // Use type assertions to ensure that the value's a JSON object
    switch jsonObj := v.(type) {
    // The value is an Item, represented as a generic interface
    case interface{}:
    var item Item
    // Access the values in the JSON object and place them in an Item
    for itemKey, itemValue := range jsonObj.(map[string]interface{}) {
    switch itemKey {
    case "Item1":
    // Make sure that Item1 is a string
    switch itemValue := itemValue.(type) {
    case string:
    item.Item1 = itemValue
    default:
    fmt.Println("Incorrect type for", itemKey)
    }
    case "Item2":
    // Make sure that Item2 is a number; all numbers are transformed to float64
    switch itemValue := itemValue.(type) {
    case float64:
    item.Item2 = int(itemValue)
    default:
    fmt.Println("Incorrect type for", itemKey)
    }
    default:
    fmt.Println("Unknown key for Item found in JSON")
    }
    }
    fmt.Println(item)
    // Not a JSON object; handle the error
    default:
    fmt.Println("Expecting a JSON object; got something else")
    }
    }

    }