properties

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2023 License: MIT Imports: 13 Imported by: 2

README

Properties

GitHub go.mod Go version Unit-Tests GitHub tag (latest SemVer) Go Report Card Go Reference Coverage Status

properties - Java Properties format contents parse, marshal and unmarshal library.

  • Generic properties contents parser, marshal and unmarshal
  • Support Marshal and Unmarshal like json package
  • Support line comments start with !, #
    • enhanced: allow //, /* multi line comments */
  • Support multi line string value, end with \\
    • enhanced: allow '''multi line string'''', """multi line string"""
  • Support value refer parse by var. format: ${some.other.key}
  • Support ENV var parse. format: ${APP_ENV}, ${APP_ENV | default}

中文说明

Install

go get github.com/gookit/properties

Usage

Example properties contents:

name = inhere
age = 345
only-key = 
env-key = ${SHELL | bash}

 ##### comments1
top.sub.key0 = a string value
top.sub.key1 = "a quote value1"
top.sub.key2 = 'a quote value2'
/* comments 1.1 */
top.sub.key3 = 234

! inline list
top2.inline.list.ids = [234, 345, 456]

# use var refer
top2.sub.var-refer = ${top.sub.key0}

/*
multi line
comments
*/
top2.sub.key2-other = has-char

# comments 2
top.sub.key3 = false

# slice list
top.sub.key4[0] = abc
top.sub.key4[1] = def

## --- comments 3 ---
top.sub.key5[0].f1 = ab
top.sub.key5[1].f2 = de

# multi line value
top.sub2.mline1 = """multi line
value
"""

# multi line value2
top.sub2.mline2 = this is \
multi line2 \
value

Parse to data

  p := properties.NewParser(
      properties.ParseEnv,
      properties.ParseInlineSlice,
  )
  p.Parse(text)
  fmt.Println("\ndata map:")
  dump.NoLoc(p.Data)

Output:

maputil.Data { #len=6
  "name": string("inhere"), #len=6
  "age": string("345"), #len=3
  "only-key": string(""), #len=0
  "env-key": string("/bin/zsh"), #len=8
  "top": map[string]interface {} { #len=2
    "sub": map[string]interface {} { #len=6
      "key5": []map[string]interface {} [ #len=2
        map[string]interface {} { #len=1
          "f1": string("ab"), #len=2
        },
        map[string]interface {} { #len=1
          "f2": string("de"), #len=2
        },
      ],
      "key0": string("a string value"), #len=14
      "key1": string("a quote value1"), #len=14
      "key2": string("a quote value2"), #len=14
      "key3": string("false"), #len=5
      "key4": []string [ #len=2
        string("abc"), #len=3
        string("def"), #len=3
      ],
    },
    "sub2": map[string]interface {} { #len=2
      "mline2": string("this is multi line2 value"), #len=25
      "mline1": string("multi line
value
"), #len=17
    },
  },
  "top2": map[string]interface {} { #len=2
    "sub": map[string]interface {} { #len=2
      "var-refer": string("a string value"), #len=14
      "key2-other": string("has-char"), #len=8
    },
    "inline": map[string]interface {} { #len=1
      "list": map[string]interface {} { #len=1
        "ids": []string [ #len=3
          string("234"), #len=3
          string("345"), #len=3
          string("456"), #len=3
        ],
      },
    },
  },
},

Parse and binding struct

package main

import (
	"fmt"

	"github.com/gookit/properties"
)

func Example() {
	text := `
# properties string
name = inhere
age = 200
`

	p, err := properties.Parse(text)
	if err != nil {
		panic(err)
	}

	type MyConf struct {
		Name string `properties:"name"`
		Age  int    `properties:"age"`
	}

	cfg := &MyConf{}
	err = p.MapStruct("", cfg)
	if err != nil {
		panic(err)
	}

	fmt.Println(*cfg)

	// Output:
	// {inhere 200}
}

Marshal/Unmarshal

  • Marshal(v any) ([]byte, error)
  • Unmarshal(v []byte, ptr any) error

Example: Unmarshal:

cfg := &MyConf{}
err := properties.Unmarshal([]byte(text), cfg)
if err != nil {
    panic(err)
}

fmt.Println(*cfg)

Example: Marshal

data := map[string]any{
	"name": "inhere",
	"age":  234,
	"str1": "a string",
	"str2": "a multi \nline string",
	"top": map[string]any{
		"sub0": "val0",
		"sub1": []string{"val1-0", "val1-1"},
	},
}

bs, err = properties.Marshal(data)
if err != nil {
	panic(err)
}

fmt.Println(string(bs))

Output:

str1=a string
str2=a multi \
line string
top.sub1[0]=val1-0
top.sub1[1]=val1-1
top.sub0=val0
name=inhere
age=234

Config management

If you want to support multiple formats and multiple file loading, it is recommended to use gookit/config

  • Support multi formats: JSON(default), INI, Properties, YAML, TOML, HCL
  • Support multi file loading and will auto merge loaded data

Gookit packages

  • gookit/ini INI parse by golang. INI config data management library.
  • gookit/rux Simple and fast request router, web framework for golang
  • gookit/gcli build CLI application, tool library, running CLI commands
  • gookit/event Lightweight event manager and dispatcher implements by Go
  • gookit/cache Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
  • gookit/config Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
  • gookit/color A command-line color library with true color support, universal API methods and Windows support
  • gookit/filter Provide filtering, sanitizing, and conversion of golang data
  • gookit/validate Use for data validation and filtering. support Map, Struct, Form data
  • gookit/goutil Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
  • More, please see https://github.com/gookit

See also

License

MIT

Documentation

Overview

Package properties provide Java Properties format contents parse, marshal and unmarshal library.

Example
package main

import (
	"fmt"

	"github.com/gookit/properties"
)

func main() {
	text := `
# properties string
name = inhere
age = 200
`

	p, err := properties.Parse(text)
	if err != nil {
		panic(err)
	}

	type MyConf struct {
		Name string `properties:"name"`
		Age  int    `properties:"age"`
	}

	cfg := &MyConf{}
	err = p.MapStruct("", cfg)
	if err != nil {
		panic(err)
	}

	fmt.Println(*cfg)

}
Output:

{inhere 200}

Index

Examples

Constants

View Source
const (
	MultiLineValMarkS = "'''"
	MultiLineValMarkD = `"""`
	MultiLineValMarkQ = "\\"
	MultiLineCmtEnd   = "*/"
	VarRefStartChars  = "${"
)

special chars consts

Variables

View Source
var DefaultTagName = "properties"

DefaultTagName for mapping data to struct.

View Source
var ErrNotFound = errors.New("this key does not exists")

ErrNotFound error

Functions

func Decode

func Decode(v []byte, ptr any) error

Decode parse properties text and decode to struct

func Encode

func Encode(v any) ([]byte, error)

Encode data(struct, map) to properties text

func Marshal

func Marshal(v any) ([]byte, error)

Marshal data(struct, map) to properties text

Example
package main

import (
	"fmt"

	"github.com/gookit/properties"
)

func main() {
	type MyConf struct {
		Name string `properties:"name"`
		Age  int    `properties:"age"`
	}

	cfg := &MyConf{
		Name: "inhere",
		Age:  300,
	}

	bts, err := properties.Marshal(cfg)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(bts))

	// Output like:
	// name=inhere
	// age=300
}
Output:

func ParseEnv

func ParseEnv(opts *Options)

ParseEnv open parse ENV var string.

func ParseInlineSlice

func ParseInlineSlice(opts *Options)

ParseInlineSlice open parse inline slice

func ParseTime

func ParseTime(opts *Options)

ParseTime open parse time string.

func Unmarshal

func Unmarshal(v []byte, ptr any) error

Unmarshal parse properties text and decode to struct

Example
package main

import (
	"fmt"
	"time"

	"github.com/gookit/properties"
)

func main() {
	text := `
# properties string
name = inhere
age = 200

project.name = properties
project.version = v1.0.1
# parse time string
project.cache-time = 10s

project.repo.name = ${project.name}
project.repo.url = https://github.com/gookit/properties
`

	type Repo struct {
		Name string `properties:"name"`
		URL  string `properties:"url"`
	}

	type Project struct {
		Name      string        `properties:"name"`
		Version   string        `properties:"version"`
		CacheTime time.Duration `properties:"cache-time"`
		Repo      Repo          `properties:"repo"`
	}

	type MyConf struct {
		Name    string  `properties:"name"`
		Age     int     `properties:"age"`
		Project Project `properties:"project"`
	}

	cfg := &MyConf{}
	err := properties.Unmarshal([]byte(text), cfg)
	if err != nil {
		panic(err)
	}

	fmt.Println(*cfg)

}
Output:

{inhere 200 {properties v1.0.1 10s {properties https://github.com/gookit/properties}}}

func ValDecodeHookFunc

func ValDecodeHookFunc() mapstructure.DecodeHookFunc

ValDecodeHookFunc returns a mapstructure.DecodeHookFunc that parse time string

func WithDebug

func WithDebug(opts *Options)

WithDebug open debug mode

Types

type Encoder

type Encoder struct {

	// TagName for encode a struct. default: properties
	TagName string
	// contains filtered or unexported fields
}

Encoder struct

func NewEncoder

func NewEncoder() *Encoder

NewEncoder instance.

func (*Encoder) Encode

func (e *Encoder) Encode(v any) ([]byte, error)

Encode data(struct, map) to properties text

func (*Encoder) Marshal

func (e *Encoder) Marshal(v any) ([]byte, error)

Marshal data(struct, map) to properties text

type OpFunc

type OpFunc func(opts *Options)

OpFunc custom option func

func WithTagName

func WithTagName(tagName string) OpFunc

WithTagName custom tag name on binding struct

type Options

type Options struct {
	// Debug open debug mode
	Debug bool
	// ParseEnv parse ENV var name, default True. eg: "${SHELL}"
	ParseEnv bool
	// ParseVar reference. eg: "${other.var.name}". default: true
	ParseVar bool
	// ParseTime string on binding struct. eg: 3s -> 3*time.Second
	ParseTime bool
	// TagName for binding data to struct. default: properties
	TagName string
	// TrimValue trim "\n" for value string. default: false
	TrimValue bool

	// InlineComment support split inline comments. default: false
	//
	// allow chars: #, //
	InlineComment bool
	// InlineSlice support parse the inline slice. eg: [23, 34]. default: false
	InlineSlice bool
	// MapStructConfig for binding data to struct.
	MapStructConfig mapstructure.DecoderConfig
	// BeforeCollect value handle func, you can return a new value.
	BeforeCollect func(name string, val any) any
}

Options for config

type Parser

type Parser struct {
	maputil.Data
	// contains filtered or unexported fields
}

Parser for parse properties contents

func NewParser

func NewParser(optFns ...OpFunc) *Parser

NewParser instance

func Parse

func Parse(text string, optFns ...OpFunc) (*Parser, error)

Parse properties text contents

func (*Parser) Comments

func (p *Parser) Comments() map[string]string

Comments data

func (*Parser) Decode added in v0.2.1

func (p *Parser) Decode(ptr any) error

Decode the parsed data to struct ptr

func (*Parser) MapStruct

func (p *Parser) MapStruct(key string, ptr any) error

MapStruct mapping data to a struct ptr

func (*Parser) Parse

func (p *Parser) Parse(text string) error

Parse text contents

func (*Parser) ParseBytes

func (p *Parser) ParseBytes(bs []byte) error

ParseBytes text contents

func (*Parser) ParseFrom

func (p *Parser) ParseFrom(r io.Reader) error

ParseFrom contents

func (*Parser) SMap

func (p *Parser) SMap() maputil.SMap

SMap data

func (*Parser) Unmarshal

func (p *Parser) Unmarshal(v []byte, ptr any) error

Unmarshal parse properties text and decode to struct

func (*Parser) WithOptions

func (p *Parser) WithOptions(optFns ...OpFunc) *Parser

WithOptions for the parser

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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