properties

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

Release Reference DeepWiki Test

Insights Insights

go-properties

Loading properties files for Go.

go-properties is a lightweight Go library for loading and managing .properties configuration files.

Parse Java-style .properties files with support for quoting, escaping, multi-line values, and variable references (environment variables and cross-property lookups). Includes a trie-based lookup structure and optional autoloading of profile-specific configuration files, inspired by Spring Boot's configuration model.

Features

  • Load properties files.
  • Trie tree based property lookup.
  • Autoload properties files.

Usages

Properties file syntax

Properties key syntax:

# 'a'-'z', 'A'-'Z', '0'-'9', '_', '.', '-', are allowed for keys.
# Whitespaces are allowed around the seperator '='.
foo = ok
foo=ok
foo_bar=ok
foo.bar=ok
foo-bar=ok

Single line:

# Single quotes and double quotes are removed if entire value is enclosed.
foo=bar          >> bar
foo="bar"        >> bar
foo='bar'        >> bar
foo='b"r'        >> b"r
foo="b'r"        >> b'r

Multiple lines:

# The "foo" will be "barbaz".
# Line breaks of LF and CRLF are removed.
# BOTH single quotes and double quotes can be used to enclose multiple lines.
foo="
bar
baz
"

Comments:

# Sharp '#' can be used for commenting.
# It must not be in the scope of single quotes and double quotes.
# It must have at least 1 white space before '#' if the comment is inlined.
# comment            >> Comment is appropriately parsed.
FOO=BAR # comment    >> Comment is appropriately parsed.
FOO=BAR# comment     >> '#' is not parsed as comment. It is considered as a part of the value.

Escapes:

# '\\' can be used for escaping characters by following the 3 rules.
# 1. '\\' always escapes special character of ', ", \\, #
# 2. '\\' is ignored when it is not in the scope of single quotes or double quotes.
# 3. '\\'n or "\n" is replaced to LF, '\\'r or "\r" to CR, '\\'t or "\t" to TAB.
foo=ba\"r      >> ba"r
foo=ba\'r      >> ba'r
foo="ba\"r"    >> ba"r
foo=ba\r       >> bar ('\' is not in a scope of single or double quotes.)
foo="ba\nr"    >> ba<LF>r (\n is, if in a scope of quotes, converted into a line break.)
foo="ba\rr"    >> ba<CR>r (\r is, if in a scope of quotes, converted into a carriage return.)
foo="ba\tr"    >> ba<TAB>r (\t is, if in a scope of quotes, converted into a tab space.)

Referencing (Environmental variables and other properties):

# Other properties and environmental variables can be referenced by ${} with following steps.
# 1. Lookup environmental variable.
# 2. Convert the key to environmental variable and lookup environmental variable.
# 3. Lookup property.
# For example, with the following example, value will be resolved by the order of
# LookupEnv("bar.baz") > LookupEnv(ToEnvName("bar.baz")) > LookupProperty("bar.baz").
# Here, ToEnvName transforms the key to upper cases and replaces '-' and '.' to '_'.
FOO=${bar.baz}
Parse properties

Properties can be parsed with the methods:

  • Parse([]byte) (map[string]string, error)
  • ParseReader(io.Reader) (map[string]string, error)

For example:

data := `
server.port = 8080
server.tls.cert = /tmp/cert.pem
server.tls.key  = /tmp/key.pem
`
props, err := properties.Parse([]byte(data))
if err != nil {
    panic(err)
}

fmt.Println(props["server.port"])     // "8080"
fmt.Println(props["server.tls.cert"]) // "/tmp/cert.pem"
fmt.Println(props["server.tls.key"])  // "/tmp/key.pem"
Get/Set properties

Properties type provides useful methods.

  • Set(key string, value any): set properties from code
  • Get(key string) (any, error): get properties with a key
  • GetAs[T any](key string) (T, error): get properties as the specified type

Properties can be created from parsed properties in map.

Example:

data := `
server.port = 8080
server.tls.cert = /tmp/cert.pem
server.tls.key  = /tmp/key.pem
debug.enabled = true
`

mapProps, err := properties.Parse([]byte(data))
if err != nil {
    panic(err)
}

// Create a properties.
props := properties.NewProperties(mapProps)

// Set more properties
props.Set("server.listen", "0.0.0.0")

// Get properties
fmt.Println(props.Get("server.listen"))             // "0.0.0.0"
fmt.Println(props.GetAs[int]("server.port"))        // 8080
fmt.Println(props.GetAs[string]("server.tls.cert")) // "/tmp/cert.pem"
fmt.Println(props.GetAs[string]("server.tls.key"))  // "/tmp/key.pem"
fmt.Println(props.GetAs[bool]("debug.enabled"))     // true
Autoload properties

autoload package provides autoloading of properties files. It loads application.properties and application-${profile}.properties by default. The ${profile} can be set with the environmental variable PROPERTIES_ACTIVE_PROFILE.

Example:

import (
    "fmt"
    "github.com/aileron-projects/go-properties/autoload"
)

func main() {
    props := autoload.Props
    fmt.Println(props.GetAs[string]("server.port"))
    fmt.Println(props.GetAs[string]("server.listen"))
    fmt.Println(props.GetAs[int]("server.read-timeout"))
}

Directory and file names can be set from code using the global variables.

var (
    PropsDir       = "./"
    PropsPath      = "application.properties"
    ProfilePattern = "application-${profile}.properties"
    Profile        = os.Getenv("PROPERTIES_ACTIVE_PROFILE")
)
Referencing environment variables

Environment variables can be referenced by ${...}. If the variable is not set, the ${...} is left as it is.

${...} can be escaped by \$\{...\}.

reference = ${FOO}
escaped = \$\{BAR\}
Referencing other property

Other properties can be referenced with ${...} like environment variables.

Environment variable FOO_BAR is prior to the property foo.bar when resolving the references of ${...}.

foo.bar = baz
reference = ${foo.bar}

Docs & Examples

References

Documentation

Overview

Example
package main

import (
	"fmt"

	"github.com/aileron-projects/go-properties"
)

func main() {
	data := `
server.port = 8080
server.tls.cert = /tmp/cert.pem
server.tls.key  = /tmp/key.pem
`
	props, err := properties.Parse([]byte(data))
	if err != nil {
		panic(err)
	}

	fmt.Println("server.port:", props["server.port"])
	fmt.Println("server.tls.cert:", props["server.tls.cert"])
	fmt.Println("server.tls.key:", props["server.tls.key"])
}
Output:
server.port: 8080
server.tls.cert: /tmp/cert.pem
server.tls.key: /tmp/key.pem

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound = errors.New("not found")
	ErrConvert  = errors.New("cannot convert data type from string")
)

Functions

func Load

func Load(files ...string) (map[string]string, error)

Load loads properties from files. Duplicated keys are always overwritten. See Parse for file formats and [Resolve] for file syntax.

func LoadReaders

func LoadReaders(readers ...io.Reader) (map[string]string, error)

LoadReaders loads envirproperties from files. Duplicated keys are always overwritten.

func Parse

func Parse(b []byte) (map[string]string, error)

Parse parses properties from the given bytes. Typically Parse parses key-values from files such as .properties file. Parse resolves embedded environmental variables in the b.

Input specifications:

Key syntax:
	# 'a'-'z', 'A'-'Z', '0'-'9', '_', '.', '-', are allowed for keys.
	# Whitespaces are allowed around the seperator '='.
	foo = ok
	foo=ok
	foo_bar=ok
	foo.bar=ok
	foo-bar=ok

Single line:
	# Single quotes and double quotes are removed if entire value is enclosed.
	foo=bar          >> bar
	foo="bar"        >> bar
	foo='bar'        >> bar
	foo='b"r'        >> b"r
	foo="b'r"        >> b'r

Multiple lines:
	# The "foo" will be "barbaz".
	# Line breaks of LF and CRLF are removed.
	# BOTH single quotes and double quotes can be used to enclose multiple lines.
	foo="
	bar
	baz
	"

Comments:
	# Sharp '#' can be used for commenting.
	# It must not be in the scope of single quotes and double quotes.
	# It must have at least 1 white space before '#' if the comment is inlined.
	# comment            >> Comment is appropriately parsed.
	FOO=BAR # comment    >> Comment is appropriately parsed.
	FOO=BAR# comment     >> '#' is not parsed as comment. It is considered as a part of the value.

Escapes:
	# '\\' can be used for escaping characters by following the 3 rules.
	# 1. '\\' always escapes special character of ', ", \\, #
	# 2. '\\' is ignored when it is not in the scope of single quotes or double quotes.
	# 3. '\\'n or "\n" is replaced to LF, '\\'r or "\r" to CR, '\\'t or "\t" to TAB.
	foo=ba\"r      >> ba"r
	foo=ba\'r      >> ba'r
	foo="ba\"r"    >> ba"r
	foo=ba\r       >> bar ('\' is not in a scope of single or double quotes.)
	foo="ba\nr"    >> ba<LF>r (\n is, if in a scope of quotes, converted into a line break.)
	foo="ba\rr"    >> ba<CR>r (\r is, if in a scope of quotes, converted into a carriage return.)
	foo="ba\tr"    >> ba<TAB>r (\t is, if in a scope of quotes, converted into a tab space.)

Referencing:
	# Other properties and environmental variables can be referenced by ${} with following steps.
	# 1. Lookup environmental variable.
	# 2. Convert the key to environmental variable and lookup environmental variable.
	# 3. Lookup property.
	# For example, with the following example, value will be resolved by the order of
	# LookupEnv("bar.baz") > LookupEnv(ToEnvName("bar.baz")) > LookupProperty("bar.baz").
	# Here, ToEnvName transforms the key to upper cases and replaces '-' and '.' to '_'.
	FOO=${bar.baz}
Example (ReferenceEnv)
package main

import (
	"fmt"
	"os"

	"github.com/aileron-projects/go-properties"
)

func main() {
	os.Setenv("EXAMPLE", "example")
	defer func() { os.Unsetenv("EXAMPLE") }()

	data := `reference = ${EXAMPLE}`

	props, err := properties.Parse([]byte(data))
	if err != nil {
		panic(err)
	}

	// Environmental variable is prior to the property in file.
	fmt.Println("reference:", props["reference"])
}
Output:
reference: example
Example (ReferenceProperty)
package main

import (
	"fmt"

	"github.com/aileron-projects/go-properties"
)

func main() {
	data := `
foo.bar = baz
reference = ${foo.bar}
`
	props, err := properties.Parse([]byte(data))
	if err != nil {
		panic(err)
	}

	fmt.Println("reference:", props["reference"])
}
Output:
reference: baz
Example (ReferencePropertyEnv)
package main

import (
	"fmt"
	"os"

	"github.com/aileron-projects/go-properties"
)

func main() {
	os.Setenv("FOO_BAR", "BAZ")
	defer func() { os.Unsetenv("FOO_BAR") }()

	data := `
foo.bar = baz
reference = ${foo.bar}
`
	props, err := properties.Parse([]byte(data))
	if err != nil {
		panic(err)
	}

	// Environmental variable is prior to the property in file.
	fmt.Println("reference:", props["reference"])
}
Output:
reference: BAZ

func ParseReader

func ParseReader(r io.Reader) (map[string]string, error)

Parse parses properties from the reader. See Parse for more details.

Types

type Error

type Error struct {
	Inner error  // Inner is the inner error.
	Type  string // Type is the error type.
	Msg   string // Msg is the error message.
}

Error is the property related error.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Properties

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

Properties provides priperties.

Example
package main

import (
	"fmt"

	"github.com/aileron-projects/go-properties"
)

func main() {
	data := `
server.port = 8080
server.tls.cert = /tmp/cert.pem
server.tls.key  = /tmp/key.pem
debug.enabled = true
`

	mapProps, err := properties.Parse([]byte(data))
	if err != nil {
		panic(err)
	}

	props := properties.NewProperties(mapProps)

	// Set more properties
	props.Set("server.listen", "0.0.0.0")

	// Get properties
	fmt.Println(props.Get("server.listen"))
	fmt.Println(props.GetAs[int]("server.port"))
	fmt.Println(props.GetAs[string]("server.tls.cert"))
	fmt.Println(props.GetAs[string]("server.tls.key"))
	fmt.Println(props.GetAs[bool]("debug.enabled"))
}
Output:
0.0.0.0 <nil>
8080 <nil>
/tmp/cert.pem <nil>
/tmp/key.pem <nil>
true <nil>

func NewProperties

func NewProperties(props map[string]string) *Properties

NewProperties creates new instance of Properties. If props is not empty, properties will be set to the returned Properties.

func (*Properties) Get

func (p *Properties) Get(key string) (any, error)

Get returns a property value if exists. Get returns ErrNotFound if the key was not found.

func (*Properties) GetAs

func (p *Properties) GetAs[T any](key string) (T, error)

Get returns a property value with the specified type T if exists.

func (*Properties) Set

func (p *Properties) Set(key string, value any)

Set sets the property.

Directories

Path Synopsis
examples
autoloading command

Jump to

Keyboard shortcuts

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