Skip to content

Instantly share code, notes, and snippets.

@pontiyaraja
Forked from mjohnsullivan/parse_json.go
Created July 12, 2019 06:45
Show Gist options
  • Save pontiyaraja/06f03d3fb837dd25b060b6347d13ea0e to your computer and use it in GitHub Desktop.
Save pontiyaraja/06f03d3fb837dd25b060b6347d13ea0e to your computer and use it in GitHub Desktop.
Parse JSON objects with arbitrary key names in Go using interfaces and type assertions
// 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")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment