Skip to content

karlseguin/typed

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Typed

Making map[string]interface{} slightly less painful

It isn't always desirable or even possible to decode JSON into a structure. That, unfortunately, leaves us with writing ugly code around map[string]interface{} and []interace{}.

This library hopes to make that slightly less painful.

Install

go get github.com/karlseguin/typed

Note

While the library could be used with any map[string]interface{}, it is tailored to be used with encoding/json. Specifically, it won't ever try to convert data, except for integers (which encoding/json treats as floats).

Usage:

A typed wrapper around a map[string]interface{} can be created in one of three ways:

// directly from a map[string]interace{}
typed := typed.New(a_map)

// from a json []byte
typed, err := typed.Json(data)

// from a file containing JSON
typed, err := typed.JsonFile(path)

Once we have a typed wrapper, we can use various functions to navigate the structure:

  • Bool(key string) bool

  • Int(key string) int

  • Float(key string) float64

  • String(key string) string

  • Object(key string) typed.Type

  • Interface(key string) interface{}

  • BoolOr(key string, defaultValue bool) bool

  • IntOr(key string, defaultValue int) int

  • FloatOr(key string, defaultValue float64) float64

  • StringOr(key string, defaultValue string) string

  • ObjectOr(key string, defaultValue map[string]interface{}) typed.Type

  • InterfaceOr(key string, defaultValue interface{}) interface{}

  • BoolMust(key string) bool

  • IntMust(key string) int

  • FloatMust(key string) float

  • StringMust(key string) string

  • ObjectMust(key string) typed.Type

  • `InterfaceMust(key string) interface{}``

  • BoolIf(key string) (bool, bool)

  • IntIf(key string) (int, bool)

  • FloatIf(key string) (float, bool)

  • StringIf(key string) (string, bool)

  • ObjectIf(key string) (typed.Type, bool)

  • InterfaceIf(key string) (interface{}, bool)

We can also extract arrays via:

  • Bools(key string) []bool
  • Ints(key string) []int
  • Ints64(key string) []int64
  • Floats(key string) []float64
  • Strings(key string) []string
  • StringsOr(key string, defaultValue []string) []string
  • BoolsOr(key string, defaultValue []bool) []bool
  • IntsOr(key string, defaultValue []int) []int
  • Ints64Or(key string, defaultValue []int64) []int64
  • FloatsOr(key string, defaultValue []float64) []float64

We can extract nested objects, other as another typed wrapper, or as a raw map[string]interface{}:

  • Object(key string) Typed

  • ObjectOr(key string, map[string]interface) Typed

  • ObjectIf(key string) (Typed, bool)

  • Objects(key string) []Typed

  • Map(key string) map[string]interface{}

  • MaoOr(key string, map[string]interface) map[string]interface{}

  • MapIf(key string) (map[string]interface{}, bool)

  • Maps(key string) []map[string]interface{}

We can extract key value pairs:

  • StringBool(key string) map[string]bool
  • StringInt(key string) map[string]int
  • StringFloat(key string) map[string]float64
  • StringString(key string) map[string]string
  • StringObject(key string) map[string]Typed

Example

package main

import (
  "fmt"
  "typed"
)

func main() {
  json := `
{
  "log": true,
  "name": "leto",
  "percentiles": [75, 85, 95],
  "server": {
    "port": 9001,
    "host": "localhost"
  },
  "cache": {
    "users": {"ttl": 5}
  },
  "blocked": {
    "10.10.1.1": true
  }
}`
  typed, err := typed.JsonString(json)
  if err != nil {
    fmt.Println(err)
  }

  fmt.Println(typed.Bool("log"))
  fmt.Println(typed.String("name"))
  fmt.Println(typed.Ints("percentiles"))
  fmt.Println(typed.FloatOr("load", 0.5))

  server := typed.Object("server")
  fmt.Println(server.Int("port"))
  fmt.Println(server.String("host"))

  fmt.Println(typed.Map("server"))

  fmt.Println(typed.StringObject("cache")["users"].Int("ttl"))
  fmt.Println(typed.StringBool("blocked")["10.10.1.1"])
}

Misc

To Bytes

ToBytes(key string) ([]byte, error) can be used to get the JSON data, as a []byte, from the Type. KeyNotFound will be returned if the key isn't valid.

Alternatively, MustBytes(key string) []byte can be used. It will panic on error.

Root Array

Support for JSON document with arrays at their root is supported. Use the JsonArray(data []byte), JsonStringArray(data string) and JsonFileArray(path string) to receive an []Typed

If the array has primitive values, the syntax is a little awkward. The key for the field is "0":

json := `[1, {"name": "leto"}, "spice"]`

typed, err := typed, err := typed.JsonStringArray(json)
if err != nil {
  panic(err)
}
println(typed[0].Int("0"))
println(typed[1].String("name"))
println(typed[2].String("0"))

JsonWriter

The JsonWriter library provides the opposite functionality: a lightweight approaching to writing JSON data.

About

A wrapper around map[string]interface{} to provide some strong typing

Resources

License

Stars

Watchers

Forks

Packages

No packages published