viper/internal/encoding/javaproperties/codec.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
}