forked from mirror/viper
78 lines
1.5 KiB
Go
78 lines
1.5 KiB
Go
|
package javaproperties
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/magiconair/properties"
|
||
|
"github.com/spf13/cast"
|
||
|
)
|
||
|
|
||
|
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding.
|
||
|
type Codec struct {
|
||
|
KeyDelimiter string
|
||
|
}
|
||
|
|
||
|
func (c Codec) Encode(v map[string]interface{}) ([]byte, error) {
|
||
|
p := properties.NewProperties()
|
||
|
|
||
|
flattened := map[string]interface{}{}
|
||
|
|
||
|
flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter())
|
||
|
|
||
|
keys := make([]string, 0, len(flattened))
|
||
|
|
||
|
for key := range flattened {
|
||
|
keys = append(keys, key)
|
||
|
}
|
||
|
|
||
|
sort.Strings(keys)
|
||
|
|
||
|
for _, key := range keys {
|
||
|
_, _, err := p.Set(key, cast.ToString(flattened[key]))
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var buf bytes.Buffer
|
||
|
|
||
|
_, err := p.WriteComment(&buf, "#", properties.UTF8)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return buf.Bytes(), nil
|
||
|
}
|
||
|
|
||
|
func (c Codec) Decode(b []byte, v map[string]interface{}) error {
|
||
|
p, err := properties.Load(b, properties.UTF8)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
for _, key := range p.Keys() {
|
||
|
// ignore existence check: we know it's there
|
||
|
value, _ := p.Get(key)
|
||
|
|
||
|
// recursively build nested maps
|
||
|
path := strings.Split(key, c.keyDelimiter())
|
||
|
lastKey := strings.ToLower(path[len(path)-1])
|
||
|
deepestMap := deepSearch(v, path[0:len(path)-1])
|
||
|
|
||
|
// set innermost value
|
||
|
deepestMap[lastKey] = value
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c Codec) keyDelimiter() string {
|
||
|
if c.KeyDelimiter == "" {
|
||
|
return "."
|
||
|
}
|
||
|
|
||
|
return c.KeyDelimiter
|
||
|
}
|