codec.go (1905B)
1 package javaproperties 2 3 import ( 4 "bytes" 5 "sort" 6 "strings" 7 8 "github.com/magiconair/properties" 9 "github.com/spf13/cast" 10 ) 11 12 // Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding. 13 type Codec struct { 14 KeyDelimiter string 15 16 // Store read properties on the object so that we can write back in order with comments. 17 // This will only be used if the configuration read is a properties file. 18 // TODO: drop this feature in v2 19 // TODO: make use of the global properties object optional 20 Properties *properties.Properties 21 } 22 23 func (c *Codec) Encode(v map[string]interface{}) ([]byte, error) { 24 if c.Properties == nil { 25 c.Properties = properties.NewProperties() 26 } 27 28 flattened := map[string]interface{}{} 29 30 flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) 31 32 keys := make([]string, 0, len(flattened)) 33 34 for key := range flattened { 35 keys = append(keys, key) 36 } 37 38 sort.Strings(keys) 39 40 for _, key := range keys { 41 _, _, err := c.Properties.Set(key, cast.ToString(flattened[key])) 42 if err != nil { 43 return nil, err 44 } 45 } 46 47 var buf bytes.Buffer 48 49 _, err := c.Properties.WriteComment(&buf, "#", properties.UTF8) 50 if err != nil { 51 return nil, err 52 } 53 54 return buf.Bytes(), nil 55 } 56 57 func (c *Codec) Decode(b []byte, v map[string]interface{}) error { 58 var err error 59 c.Properties, err = properties.Load(b, properties.UTF8) 60 if err != nil { 61 return err 62 } 63 64 for _, key := range c.Properties.Keys() { 65 // ignore existence check: we know it's there 66 value, _ := c.Properties.Get(key) 67 68 // recursively build nested maps 69 path := strings.Split(key, c.keyDelimiter()) 70 lastKey := strings.ToLower(path[len(path)-1]) 71 deepestMap := deepSearch(v, path[0:len(path)-1]) 72 73 // set innermost value 74 deepestMap[lastKey] = value 75 } 76 77 return nil 78 } 79 80 func (c Codec) keyDelimiter() string { 81 if c.KeyDelimiter == "" { 82 return "." 83 } 84 85 return c.KeyDelimiter 86 }