Skip to content

Commit

Permalink
up: update some parse logic, add more tests case
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Aug 17, 2022
1 parent 99f828e commit d318b34
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 32 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

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

- Generic properties contents parser
- Generic properties contents parser, marshal and unmarshal
- Support `Marshal` and `Unmarshal` like `json` package
- Support comments withs `#`, `//`, `/* multi line comments */`
- Support multi line string value, withs `'''multi line string''''`, `"""multi line string"""`
- Support comments start withs `!`, `#`, `//`, `/* multi line comments */`
- Support multi line string value, withs `\\`, `'''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}`
- Support value refer parse by var. format: `{$key_name}`

> **[中文说明](README.zh-CN.md)**
Expand Down
24 changes: 21 additions & 3 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package properties

import "github.com/mitchellh/mapstructure"

// DefaultTagName settings
// DefaultTagName for mapping data to struct.
var DefaultTagName = "properties"

// OpFunc custom option func
Expand All @@ -12,7 +12,7 @@ type OpFunc func(opts *Options)
type Options struct {
// ParseEnv parse ENV var name, default True. eg: "${SHELL}"
ParseEnv bool
// ParseVar reference. eg: "${other.var.name}"
// ParseVar reference. eg: "${other.var.name}". default: true
ParseVar bool
// ParseTime string on binding struct. eg: 3s -> 3*time.Second
ParseTime bool
Expand All @@ -26,6 +26,8 @@ type Options struct {
//
// allow chars: #, //
InlineComment bool
// InlineSlice support parse the inline slice. eg: [23, 34]. default: false
InlineSlice bool
// TrimMultiLine trim "\n" for multi line value. default: false
TrimMultiLine bool
// BeforeCollect value handle func.
Expand All @@ -39,9 +41,25 @@ func (opts *Options) shouldAddHookFunc() bool {
return false
}

func (opts *Options) makeDecoderConfig() *mapstructure.DecoderConfig {
decConf := opts.MapStructConfig
// compatible with settings on opts.TagName
if decConf.TagName == "" {
decConf.TagName = opts.TagName
}

// add hook on decode value to struct
if opts.shouldAddHookFunc() {
decConf.DecodeHook = ValDecodeHookFunc(opts.ParseEnv, opts.ParseTime)
}

return &decConf
}

func newDefaultOption() *Options {
return &Options{
TagName: DefaultTagName,
ParseVar: true,
TagName: DefaultTagName,
// map struct config
MapStructConfig: mapstructure.DecoderConfig{
TagName: DefaultTagName,
Expand Down
18 changes: 5 additions & 13 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ func (p *Parser) setValue(key, value, comments string) {
// set value by keys
if len(keys) == 1 {
p.Data[key] = value
} else if len(p.Data) == 0 {
p.Data = maputil.MakeByKeys(keys, value)
} else {
err := p.Data.SetByKeys(keys, value)
// err := maputil.SetByKeys((*map[string]any)(&p.Data), keys, value)
Expand Down Expand Up @@ -353,20 +355,10 @@ func (p *Parser) MapStruct(key string, ptr interface{}) error {
}
}

bindConf := p.opts.MapStructConfig
// compatible with settings on opts.TagName
if bindConf.TagName == "" {
bindConf.TagName = p.opts.TagName
}

// add hook on decode value to struct
if p.opts.shouldAddHookFunc() {
bindConf.DecodeHook = ValDecodeHookFunc(p.opts.ParseEnv, p.opts.ParseTime)
}

bindConf.Result = ptr // set result struct ptr
decoder, err := mapstructure.NewDecoder(&bindConf)
decConf := p.opts.makeDecoderConfig()
decConf.Result = ptr // set result ptr

decoder, err := mapstructure.NewDecoder(decConf)
if err == nil {
err = decoder.Decode(data)
}
Expand Down
25 changes: 19 additions & 6 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (

func TestParser_Parse(t *testing.T) {
text := `
name = inhere
age = 345
##### comments1
top.sub.key0 = a string value
top.sub.key1 = "a string value"
Expand All @@ -20,35 +23,45 @@ top.sub.key2 = 234
# inline list
top2.inline.list.ids = [234, 345, 456]
# use var refer
top2.sub.var-refer = ${top.sub.key0}
/*
multi line
comments
*/
top.sub.key2-other = has-char
top2.sub.key2-other = has-char
# comments 2
top.sub.key3 = false
top.sub.key4[0] = abc # comments at end1
top.sub.key4[1] = def // comments at end2
# 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
invalid line
top.sub2.mline1 = """multi line
value
"""
top.sub2.mline2 = this is\
multi line2\
value
`

p := properties.NewParser()
err := p.Parse(text)
assert.NoErr(t, err)
fmt.Println("\ndata map:")
dump.NoLoc(p.Data)

fmt.Println("string map:")
fmt.Println("\nstring map:")
dump.NoLoc(p.SMap())

fmt.Println("comments:")
fmt.Println("\ncomments:")
dump.NoLoc(p.Comments())
}

Expand Down
25 changes: 20 additions & 5 deletions testdata/simple.properties → testdata/example.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@
app.id=9527
app.name=myapp
app.some-string = a long string value
app.var-refer = ${app.name}
app.multi-line.string = a long \
and \
multi line\
string value

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

# inline list
server.user.ids = [34, 45]

# multi line list
server.rpc.ips[0] = 127.0.0.1
server.rpc.ips[1] = 127.0.0.1

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

top.sub.key5[0].f1 = ab
top.sub.key5[1].f2 = de

spring.datasource.dynamic.strict=true

# Redis settings
Expand All @@ -16,8 +36,3 @@ spring.redis.port=6379
spring.redis.timeout=2000
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.min-idle=0


# multi line list
server.rpc.ips[0] = 127.0.0.1
server.rpc.ips[1] = 127.0.0.1
3 changes: 2 additions & 1 deletion util.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (
"github.com/mitchellh/mapstructure"
)

var refRegex = regexp.MustCompile(`^[a-z][a-z\d.]+`)
// eg: ${some.other.key} -> some.other.key
var refRegex = regexp.MustCompile(`^[a-z][a-z\d.]+$`)

func parseVarRefName(val string) (string, bool) {
if !strings.HasPrefix(val, VarRefStartChars) || !strings.HasSuffix(val, "}") {
Expand Down

0 comments on commit d318b34

Please sign in to comment.