config

package module
v0.0.0-...-0ff174c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2016 License: MIT Imports: 12 Imported by: 9

README

ozzo-config

GoDoc Build Status Coverage Status Go Report

Other languages

Description

ozzo-config is a Go package for handling configurations in Go applications. It supports

  • reading JSON (with comments), YAML, and TOML configuration files
  • merging multiple configurations
  • accessing any part of the configuration
  • configuring an object using a part of the configuration
  • adding new configuration file formats

Requirements

Go 1.2 or above.

Installation

Run the following command to install the package:

go get github.com/go-ozzo/ozzo-config

Getting Started

The following code snippet shows how you can use this package.

package main

import (
    "fmt"
    "github.com/go-ozzo/ozzo-config"
)

func main() {
    // create a Config object
    c := config.New()

    // load configuration from a JSON string
    c.LoadJSON([]byte(`{
        "Version": "2.0",
        "Author": {
            "Name": "Foo",
            "Email": "bar@example.com"
        }
    }`))

    // get the "Version" value, return "1.0" if it doesn't exist in the config
    version := c.GetString("Version", "1.0")

    var author struct {
        Name, Email string
    }
    // populate the author object from the "Author" configuration
    c.Configure(&author, "Author")

    fmt.Println(version)
    fmt.Println(author.Name)
    fmt.Println(author.Email)
    // Output:
    // 2.0
    // Foo
    // bar@example.com
}

Loading Configuration

You can load configuration in three ways:

c := config.New()

// load from one or multiple JSON, YAML, or TOML files.
// file formats are determined by their extensions: .json, .yaml, .yml, .toml
c.Load("app.json", "app.dev.json")

// load from one or multiple JSON strings
c.LoadJSON([]byte(`{"Name": "abc"}`), []byte(`{"Age": 30}`))

// load from one or multiple variables
data1 := struct {
    Name string
} { "abc" }
data2 := struct {
    Age int
} { 30 }
c.SetData(data1, data2)

When loading from multiple sources, the configuration will be obtained by merging them one after another recursively.

Accessing Configuration

You can access any part of the configuration using one of the Get methods, such as Get(), GetString(), GetInt(). These methods require a path parameter which is in the format of X.Y.Z and references the configuration value located at config["X"]["Y"]["Z"]. If a path does not correspond to a configuration value, a zero value or an explicitly specified default value will be returned by the method. For example,

// Retrieves "Author.Email". The default value "bar@example.com"
// should be returned if "Author.Email" is not found in the configuration.
email := c.GetString("Author.Email", "bar@example.com")

Changing Configuration

You can change any part of the configuration using the Set method. For example, the following code changes the configuration value config["Author"]["Email"]:

c.Set("Author.Email", "bar@example.com")

Configuring Objects

You can use a configuration to configure the properties of an object. For example, the configuration corresponding to the JSON structure {"Name": "Foo", "Email": "bar@example.com"} can be used to configure the Name and Email fields of a struct.

When configuring a nil interface, you have to specify the concrete type in the configuration via a type element in the configuration map. The type should also be registered first by calling Register() so that it knows how to create a concrete instance.

New Configuration File Formats

ozzo-config supports three configuration file formats out-of-box: JSON (can contain comments), YAML, and TOML. To support reading new file formats, you should modify the config.UnmarshalFuncMap variable by mapping a new file extension to the corresponding unmarshal function.

Documentation

Overview

Package config provides configuration handling for applications.

Example
var app struct {
	Version string
	Params  map[string]interface{}
}

// create a new configuration
c := config.New()

// load configuration from app.json and app.dev.json files
if err := c.Load("app.json", "app.dev.json"); err != nil {
	panic(err)
}

// retrieve the Version configuration value
fmt.Println(c.GetString("Version"))

// configure the app struct
if err := c.Configure(&app); err != nil {
	panic(err)
}
fmt.Println(app.Params["Key"])
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var UnmarshalFuncMap = map[string]UnmarshalFunc{
	".yaml": yaml.Unmarshal,
	".yml":  yaml.Unmarshal,
	".json": func(bytes []byte, data interface{}) (err error) {
		if bytes, err = stripJSONComments(bytes); err != nil {
			return
		}
		if err = json.Unmarshal(bytes, data); err != nil {
			return
		}
		return nil
	},
	".toml": func(bytes []byte, data interface{}) error {
		_, err := toml.Decode(string(bytes), data)
		return err
	},
}

UnmarshalFuncMap maps configuration file extensions to the corresponding unmarshal functions.

Functions

This section is empty.

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config represents a configuration that can be accessed or used to configure objects.

A configuration is a hierarchy of maps and arrays. You may use a path in the dot format to access a particular configuration value in the hierarchy. For example, the path "Path.To.Xyz" corresponds to the value config["Path"]["To"]["Xyz"].

You can also configure an object with a particular configuration value by calling the Configure() method, which sets the object fields with the corresponding configuration value.

Config can be loaded from one or multiple JSON, YAML, or TOML files. Files loaded latter will be merged with the earlier ones. You may also directly populate Config with the data in memory.

func New

func New() *Config

New creates a new Config object.

func (*Config) Configure

func (c *Config) Configure(v interface{}, path ...string) (err error)

Configure configures the specified value.

You may configured the value with the whole configuration data or a part of it by specifying the path to that part.

To configure a struct, the configuration should be a map. A struct field will be assigned with a map value whose key is the same as the field name. If a field is also struct, it will be recursively configured with the corresponding map configuration.

When configuring an interface, the configuration should be a map with a special "type" key. The "type" element specifies the type name registered by Register(). It allows the method to create a correct object given a type name.

Note that the value to be configured must be passed in as a pointer. You may specify a path to use a particular part of the configuration to configure the value. If a path is not specified, the whole configuration will be used.

Example
var app struct {
	Version string
	Params  map[string]interface{}
}

c := config.New()
c.LoadJSON([]byte(`{
		"Version": "1.0-alpha",
		"Params": {
			"DataPath": "/data"
		}
	}`))
c.Configure(&app)
fmt.Println(app.Version)
fmt.Println(app.Params["DataPath"])
Output:

1.0-alpha
/data

func (*Config) Data

func (c *Config) Data() interface{}

Data returns the complete configuration data. Nil will be returned if the configuration has never been loaded before.

func (*Config) Get

func (c *Config) Get(path string, defaultValue ...interface{}) interface{}

Get retrieves the configuration value corresponding to the specified path.

The path uses a dotted format. A path "Path.To.Xyz" corresponds to the configuration value config["Path"]["To"]["Xyz"], provided both config["Path"] and config["Path"]["To"] are both valid maps. If not, a default value will be returned. If you do not specify a default value, nil will be returned. You may use array keys in the dotted format as well to access arrays in the configuration. For example, a path "Path.2.Xyz" corresponds to the value config["Path"][2]["Xyz"], if config["Path"] is an array and config["Path"][2] is a valid.

If any part of the path corresponds to an invalid value (not a map/array, or is nil), the default value will be returned. If you do not specify a default value, nil will be returned.

Note that if you specify a default value, the return value of this method will be automatically converted to the same type of the default value. If the conversion cannot be conducted, the default value will be returned.

Example
var data = []byte(`{
		"A": {
			"B1": "v1",
			"B2": {
				"C1": 300
			},
			"B3": true,
			"B4": [100, "abc"]
		}
	}`)

c := config.New()
c.LoadJSON(data)

fmt.Println(c.Get("A.B1"))
fmt.Println(c.Get("A.B2.C1"))
fmt.Println(c.Get("A.D", "not found"))
fmt.Println(c.GetBool("A.B3"))
fmt.Println(c.GetInt("A.B4.0"))
Output:

v1
300
not found
true
100

func (*Config) GetBool

func (c *Config) GetBool(path string, defaultValue ...bool) bool

GetString retrieves the bool-typed configuration value corresponding to the specified path. Please refer to Get for the detailed usage explanation.

func (*Config) GetFloat

func (c *Config) GetFloat(path string, defaultValue ...float64) float64

GetString retrieves the float64-typed configuration value corresponding to the specified path. Please refer to Get for the detailed usage explanation.

func (*Config) GetInt

func (c *Config) GetInt(path string, defaultValue ...int) int

GetString retrieves the int-typed configuration value corresponding to the specified path. Please refer to Get for the detailed usage explanation.

func (*Config) GetInt64

func (c *Config) GetInt64(path string, defaultValue ...int64) int64

GetString retrieves the int64-typed configuration value corresponding to the specified path. Please refer to Get for the detailed usage explanation.

func (*Config) GetString

func (c *Config) GetString(path string, defaultValue ...string) string

GetString retrieves the string-typed configuration value corresponding to the specified path. Please refer to Get for the detailed usage explanation.

func (*Config) Load

func (c *Config) Load(files ...string) error

Load loads configuration data from one or multiple files.

If multiple configuration files are given, the corresponding configuration data will be merged sequentially according to the rules described in SetData().

Supported configuration file formats include JSON, YAML, and TOML. The file formats are determined by the file name extensions (.json, .yaml, .yml, .toml). The method will return any file reading or parsing errors.

Note that this method will NOT clear the existing configuration data.

Example
c := config.New()
if err := c.Load("app.json", "app.dev.json"); err != nil {
	panic(err)
}
Output:

func (*Config) LoadJSON

func (c *Config) LoadJSON(data ...[]byte) error

LoadJSON loads new configuration data which are given as JSON strings.

If multiple JSON strings are given, the corresponding configuration data will be merged sequentially according to the rules described in SetData().

The method will return any JSON parsing error.

Note that this method will NOT clear the existing configuration data.

Example
var data1 = []byte(`{"A":true, "B":100, "C":{"D":"xyz"}}`)
var data2 = []byte(`{"B":200, "C":{"E":"abc"}}`)

c := config.New()
if err := c.LoadJSON(data1, data2); err != nil {
	panic(err)
}

fmt.Println(c.Get("A"))
fmt.Println(c.Get("B"))
fmt.Println(c.Get("C.D"))
fmt.Println(c.Get("C.E"))
Output:

true
200
xyz
abc

func (*Config) Register

func (c *Config) Register(name string, provider interface{}) error

Register associates a type name with a provider that creates an instance of the type. The provider must be a function with a single output. Register is mainly needed when calling Configure() to configure an object and create new instances of the specified types.

Example
c := config.New()
c.Register("MyType", func() string {
	return "my type"
})
Output:

func (*Config) Set

func (c *Config) Set(path string, value interface{}) error

Set sets the configuration value at the specified path.

The path uses a dotted format. A path "Path.To.Xyz" corresponds to the configuration value config["Path"]["To"]["Xyz"], while "Path.2.Xyz" corresponds to config["Path"][2]["Xyz"]. If a value already exists at the specified path, it will be overwritten with the new value. If a partial path has no corresponding configuration value, one will be created. For example, if the map config["Path"] has no "To" element, a new map config["Path"]["To"] will be created so that we can set the value of config["Path"]["To"]["Xyz"].

The method will return an error if it is unable to set the value for various reasons, such as the new value cannot be added to the existing array or map.

Example
c := config.New()

c.Set("A.B", 100)
c.Set("A.C", true)

fmt.Println(len(c.Get("A").(map[string]interface{})))
fmt.Println(c.GetInt("A.B"))
fmt.Println(c.GetBool("A.C"))
Output:

2
100
true

func (*Config) SetData

func (c *Config) SetData(data ...interface{})

SetData sets the configuration data.

If multiple configurations are given, they will be merged sequentially. The following rules are taken when merging two configurations C1 and C2: A). If either C1 or C2 is not a map, replace C1 with C2; B). Otherwise, add all key-value pairs of C2 to C1; If a key of C2 is also found in C1, merge the corresponding values in C1 and C2 recursively.

Note that this method will clear any existing configuration data.

Example
data1 := map[string]interface{}{
	"A": "abc",
	"B": "xyz",
}

data2 := map[string]interface{}{
	"B": "zzz",
	"C": true,
}

c := config.New()
c.SetData(data1, data2)

fmt.Println(c.Get("A"))
fmt.Println(c.Get("B"))
fmt.Println(c.Get("C"))
Output:

abc
zzz
true

type ConfigPathError

type ConfigPathError struct {
	Path    string
	Message string
}

ConfigPathError describes a path which cannot be used to set a configuration value.

func (*ConfigPathError) Error

func (s *ConfigPathError) Error() string

Error returns the error message represented by ConfigPathError

type ConfigTargetError

type ConfigTargetError struct {
	Value reflect.Value
}

ConfigTargetError describes a target value that cannot be configured

func (*ConfigTargetError) Error

func (e *ConfigTargetError) Error() string

Error returns the error message represented by ConfigTargetError

type ConfigValueError

type ConfigValueError struct {
	Path    string // path to the configuration value
	Message string // the detailed error message
}

ConfigValueError describes a configuration that cannot be used to configure a target value

func (*ConfigValueError) Error

func (e *ConfigValueError) Error() string

Error returns the error message represented by ConfigValueError

type FileTypeError

type FileTypeError string

FileTypeError describes the name of a file whose format is not supported.

func (FileTypeError) Error

func (s FileTypeError) Error() string

Error returns the error message represented by FileTypeError

type ProviderError

type ProviderError struct {
	Value reflect.Value
}

ProviderError describes a provider that was not appropriate for a type

func (*ProviderError) Error

func (e *ProviderError) Error() string

Error returns the error message represented by ProviderError

type UnmarshalFunc

type UnmarshalFunc func([]byte, interface{}) error

UnmarshalFunc parses the given configuration and populates it into the given variable.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL