Go Quickly - Parsing Anonymous JSON

Oct 2 2015

Go is great for parsing known JSON formats. But what if you don't know ahead of time what the JSON will look like? There are a few ways to handle this case in Go. On one hand, you can use the tokenizer and sequentially read through the JSON. On the other, you can simply parse the JSON into generic data types and inspect them at runtime. This short post shows how to go about this second way.

This simple example (with error handling removed) shows how to parse a JSON file into an empty interface{}:

import (
  "encoding/json"
  "os"
)

func main() {
  r, _ := os.Open("example.json")
    dec := json.NewDecoder(r)
    var thingy interface{}
  dec.Decode(&thingy)
}

At this point, thingy contains your parsed JSON. From there, you can start working on thingy by examining its contents. When parsed this way, your data will be...

  • A slice: []interface{}
  • A map: map[string]interface{}
  • nil
  • A bool, float64 (Numeric), or string

There are some sophisticated ways of examining values in Go using the reflection package, but for us we can go with a simpler method:

  if data == nil {
    // We got a JSON null.
  } if val, ok := data.([]interface{}); ok {
    // val is now a []interface{}
  } else if val, ok := data.(map[string]interface{}); ok {
    // val is now a map[string]interface{}
  } else {
    // You can continue the else/if down through the remaining
    // three types.
    }

The downside to this method is clearly the requirement that you have to do runtime type assertions to handle each and every element in your JSON structure. But it remains a viable quick-and-dirty technique for working with arbitrary JSON.

To see this method in action, you can take a look at the simple jv tool.


This article is part of the Go Quickly series (formerly Quick Go Hacks).