Documentation
¶
Overview ¶
jsonconfig contains a set of useful structures for accessing JSON data from a configuration file. It uses a pre-processor that removes //comments from the file before parsing it.
package main
import (
"github.com/callum-ramage/jsonconfig"
"fmt"
)
func main() {
config, err := jsonconfig.LoadAbstract("./configs/ExampleConfig.conf", "")
if err != nil {
return
}
fmt.Println(config["example_string"].Str)
fmt.Println(config["example_array"].Arr[0].Str)
fmt.Println(config["example_object"].Obj["example_number"].Num)
fmt.Println(config["example_object"].Obj["example_number"].Int)
//Or
fmt.Println(config["example_string"].Str)
fmt.Println(config["example_array.0"].Str)
fmt.Println(config["example_object.example_number"].Num)
fmt.Println(config["example_object.example_number"].Int)
}
Outputs
string value array value 0 5.3 5
Where ./configs/ExampleConfig.conf is
{
"example_string": "string value",
"example_array": [
"array value 0"
],
"example_object": {
"example_number": 5.3
}
}
Index ¶
- func Load(filename string, config interface{}) error
- type Configuration
- func ConvertMap(from map[string]interface{}) Configuration
- func LoadAbstract(filename string, defaults string) (config Configuration, err error)
- func LoadAbstractNoCollapse(filename string, defaults string) (config Configuration, err error)
- func LoadString(JSONString string, defaults string) (config Configuration, err error)
- type JSONValue
- type JsonCommentStripper
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Load ¶
Loads the file containing a JSON object into the provided data structure. You can provide default values by defining them in the provided data structure before handing it to this func.
Example ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
type exampleObject struct {
Example_number float64
}
type configuration struct {
Example_string string
Example_array []string
Example_object *exampleObject
Example_default int
}
func main() {
/*
./configs/ExampleConfig.conf is
{
"example_string": "string value",
"example_array": [
"array value 0"
],
"example_object": {
"example_number": 5.3
}
}
*/
config := configuration{Example_default: 4}
err := jsonconfig.Load("./configs/ExampleConfig.conf", &config)
if err != nil {
return
}
fmt.Println("example_string:", config.Example_string)
fmt.Println("example_array:", config.Example_array[0])
fmt.Println("example_object:", config.Example_object.Example_number)
fmt.Println("example_default:", config.Example_default)
}
Output: example_string: string value example_array: array value 0 example_object: 5.3 example_default: 4
Types ¶
type Configuration ¶
func ConvertMap ¶ added in v1.0.2
func ConvertMap(from map[string]interface{}) Configuration
Converts an abstract map of JSON data into a map of JSONValue.
func LoadAbstract ¶
func LoadAbstract(filename string, defaults string) (config Configuration, err error)
Loads the file containing a JSON object into an abstract map of JSONValue valueType. You can provide a default configuration by providing a partial example of the config file as a string.
Example ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
/*
./configs/ExampleConfig.conf is
{
"example_string": "string value",
"example_array": [
"array value 0"
],
"example_object": {
"example_number": 5.3
}
}
*/
config, err := jsonconfig.LoadAbstract("./configs/ExampleConfig.conf", `{"example_default": 4}`)
if err != nil {
return
}
fmt.Println("example_string:", config["example_string"].Str)
fmt.Println("example_array:", config["example_array"].Arr[0].Str)
fmt.Println("example_object:", config["example_object"].Obj["example_number"].Num)
fmt.Println("example_default:", config["example_default"].Int)
}
Output: example_string: string value example_array: array value 0 example_object: 5.3 example_default: 4
Example (Arrays) ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
/*
./configs/ExampleArrayConfig.conf is
{
"example_array": [
"array value 0",
"array value 1",
{
"handles": "objects"
},
"array value 3"
]
}
*/
config, err := jsonconfig.LoadAbstract("./configs/ExampleArrayConfig.conf", "")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("example_array.0:", config["example_array.0"].Str)
fmt.Println("example_array.1:", config["example_array.1"].Str)
fmt.Println("example_array.2:", config["example_array.2"].Obj["handles.objects"].Str)
fmt.Println("example_array.2.handles.objects:", config["example_array.2.handles.objects"].Str)
fmt.Println("example_array.3:", config["example_array.3"].Str)
fmt.Println("The array value that is an object wont be printed because it isn't a string")
for _, value := range config["example_array"].Arr {
fmt.Println(value.Str)
}
}
Output: example_array.0: array value 0 example_array.1: array value 1 example_array.2: even when split example_array.2.handles.objects: even when split example_array.3: array value 3 The array value that is an object wont be printed because it isn't a string array value 0 array value 1 array value 3
Example (Complex) ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
/*
./configs/ExampleComplexConfig.conf is
{
"example_object": {
"that": {
"goes": {
"quite": "deep"
}
},
"you ofcourse": "don't have to use all the depth"
},
"example_object.you ofcourse": "but collisions can be a pain"
}
*/
config, err := jsonconfig.LoadAbstract("./configs/ExampleComplexConfig.conf", "")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(config["example_object.that.goes.quite"].Str)
fmt.Println(config["example_object.that.doesn't.care.how.deep.you.go.even.if.it's.invalid"].Str)
fmt.Println(config["example_object.you ofcourse"].Str)
fmt.Println(config["example_object"].Obj["you ofcourse"].Str)
}
Output: deep but collisions can be a pain don't have to use all the depth
Example (Defaults) ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
/*
./configs/ExampleConfig.conf is
{
"example_string": "string value",
"example_array": [
"array value 0"
],
"example_object": {
"example_number": 5.3
}
}
*/
config, err := jsonconfig.LoadAbstract("./configs/ExampleConfig.conf", `{
"example_default": 4,
"example_string": "only a default",
"example_array": [
"arrays",
"don't",
"get",
"merged"
],
"example_object": {
"example_merge": "objects get merged",
"example_number": 6
}
}`)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("example_default:", config["example_default"].Int)
fmt.Println("example_string:", config["example_string"].Str)
fmt.Println("length of example_array:", len(config["example_array"].Arr))
fmt.Println("example_array:", config["example_array"].Arr[0].Str)
fmt.Println("example_object:", config["example_object"].Obj["example_merge"].Str)
fmt.Println("example_object:", config["example_object"].Obj["example_number"].Num)
}
Output: example_default: 4 example_string: string value length of example_array: 1 example_array: array value 0 example_object: objects get merged example_object: 5.3
func LoadAbstractNoCollapse ¶
func LoadAbstractNoCollapse(filename string, defaults string) (config Configuration, err error)
Loads the file containing a JSON object into an abstract map of JSONValue valueType. You can provide a default configuration by providing a partial example of the config file as a string. This call should be used over LoadAbstract if you wish to use range on a JSON object. The collapse performed by LoadAbstract pollutes the keys of parent objects.
func LoadString ¶
func LoadString(JSONString string, defaults string) (config Configuration, err error)
Loads the JSON formatted string into an abstract map of JSONValue valueType. You can provide a default configuration by providing a partial example of the config file as a string.
Example ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
config, err := jsonconfig.LoadString(`
{
"example_string": "string value",
"example_array": [
"array value 0"
],
"example_object": {
"example_number": 5.3
}
}
`, `{"example_default": 4}`)
if err != nil {
return
}
fmt.Println("example_string:", config["example_string"].Str)
fmt.Println("example_array:", config["example_array"].Arr[0].Str)
fmt.Println("example_object:", config["example_object"].Obj["example_number"].Num)
fmt.Println("example_default:", config["example_default"].Int)
}
Output: example_string: string value example_array: array value 0 example_object: 5.3 example_default: 4
func (Configuration) Collapse ¶
func (config Configuration) Collapse()
Flattens a configuration (map[string]JSONValue) so that you can access sub levels with a "." delimeter. This function wont overwrite any keys that already exist, so if you have a structure of the form
{
"example": {
"collision": "ignored"
},
"example.collision": "used"
}
The value "used" will be returned by config["example.collision"].
func (Configuration) Get ¶
func (config Configuration) Get(path string) JSONValue
Takes a "." delimited path and recursively uses the path, returning when a matching structure is found. So this func will return used in the following example because example.collision gets matched before example: { collision }.
{
"example": {
"collision": "ignored"
},
"example.collision": "used"
}
This func is only available because a collapsed config pollutes the parent nodes, stopping you from using
for key, value := range config {
fmt.Println(key)
}
This func also can't handle arrays so for the following config
{
"array": [
{
"value": 4
}
]
}
config.Get("array.0.value").Num will return nothing while a collapsed config config["array.0.value"].Num would return 4.
func (Configuration) MergeConfig ¶
func (config Configuration) MergeConfig(other Configuration)
Carefully copies the other Configurations values into the calling config file. If the key already exists in the calling config file then the one in the other config is ignored unless the value in the other config and the calling config are both objects. If the value is an object then the process is repeated, treating this key as a config in both the calling config and other config.
Example ¶
package main
import (
"fmt"
"github.com/callum-ramage/jsonconfig"
)
func main() {
/*
./configs/ExampleConfig1.conf is
{
"from one": 1,
"collision": "one",
"object collision": {
"from one": 1,
"collision": "one",
},
"array collision": [
"one"
]
}
./configs/ExampleConfig2.conf is
{
"from two": 2,
"collision": "two",
"object collision": {
"from two": 2,
"collision": "two",
},
"array collision": [
"two",
"three"
]
}
*/
config, err := jsonconfig.LoadAbstract("./configs/ExampleConfig1.conf", "")
if err != nil {
fmt.Println(err)
return
}
config2, err := jsonconfig.LoadAbstract("./configs/ExampleConfig2.conf", "")
if err != nil {
fmt.Println(err)
return
}
config.MergeConfig(config2)
fmt.Println("from one:", config["from one"].Num)
fmt.Println("from two:", config["from two"].Num)
fmt.Println("collision:", config["collision"].Str)
fmt.Println("object collision.from one:", config["object collision.from one"].Num)
fmt.Println("object collision.from two:", config["object collision.from two"].Num)
fmt.Println("object collision.collision:", config["object collision.collision"].Str)
fmt.Println("length of array collision:", len(config["array collision"].Arr))
fmt.Println("array collision.0:", config["array collision.0"].Str)
}
Output: from one: 1 from two: 2 collision: one object collision.from one: 1 object collision.from two: 2 object collision.collision: one length of array collision: 1 array collision.0: one
type JSONValue ¶
type JSONValue struct {
Value interface{}
Arr []JSONValue
Str string
Int int
Num float64
Bool bool
Obj Configuration
}
Is a convenience struct that makes working with abstract JSON data more tolerable. The internal values Arr and Obj can be nil, so should not be assumed to be safe.
func NewJSONValue ¶
func NewJSONValue(value interface{}) JSONValue
Creates a JSONValue from the interface provided. It attempts to fill the values Arr, Str, Int, Num, and Obj by checking against the type of the value provided.
func (JSONValue) Array ¶
Checks if the type of the JSON value is an array and if appropriate, casts it into an array of JSONValue.
func (JSONValue) Boolean ¶
Checks if the type of the JSON value is a bool and if appropriate, casts it into a bool.
func (JSONValue) Integer ¶
Checks if the type of the JSON value is a float64 and if appropriate, casts it into an int.
func (JSONValue) Number ¶
Checks if the type of the JSON value is a float64 and if appropriate, casts it into a float64.
func (JSONValue) Object ¶
func (key JSONValue) Object() Configuration
Checks if the type of the JSON value is an object and if appropriate, casts it into a map of JSONValue.
type JsonCommentStripper ¶
Outputs json with //comments removed.
func NewJsonCommentStripper ¶
func NewJsonCommentStripper(reader io.Reader) *JsonCommentStripper
Creates a new comment stripper that can be used as an intermediate layer between a JSON decoder and a json source reader.