Clean json config. Fix DefaultStrings
Showing
2 changed files
with
48 additions
and
44 deletions
| ... | @@ -17,13 +17,10 @@ package config | ... | @@ -17,13 +17,10 @@ package config |
| 17 | import ( | 17 | import ( |
| 18 | "encoding/json" | 18 | "encoding/json" |
| 19 | "errors" | 19 | "errors" |
| 20 | "fmt" | ||
| 21 | "io/ioutil" | 20 | "io/ioutil" |
| 22 | "os" | 21 | "os" |
| 23 | "path" | ||
| 24 | "strings" | 22 | "strings" |
| 25 | "sync" | 23 | "sync" |
| 26 | "time" | ||
| 27 | ) | 24 | ) |
| 28 | 25 | ||
| 29 | // JsonConfig is a json config parser and implements Config interface. | 26 | // JsonConfig is a json config parser and implements Config interface. |
| ... | @@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { | ... | @@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { |
| 41 | if err != nil { | 38 | if err != nil { |
| 42 | return nil, err | 39 | return nil, err |
| 43 | } | 40 | } |
| 41 | |||
| 42 | return js.ParseData(content) | ||
| 43 | } | ||
| 44 | |||
| 45 | // ParseData returns a ConfigContainer with json string | ||
| 46 | func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { | ||
| 44 | x := &JsonConfigContainer{ | 47 | x := &JsonConfigContainer{ |
| 45 | data: make(map[string]interface{}), | 48 | data: make(map[string]interface{}), |
| 46 | } | 49 | } |
| 47 | err = json.Unmarshal(content, &x.data) | 50 | err := json.Unmarshal(data, &x.data) |
| 48 | if err != nil { | 51 | if err != nil { |
| 49 | var wrappingArray []interface{} | 52 | var wrappingArray []interface{} |
| 50 | err2 := json.Unmarshal(content, &wrappingArray) | 53 | err2 := json.Unmarshal(data, &wrappingArray) |
| 51 | if err2 != nil { | 54 | if err2 != nil { |
| 52 | return nil, err | 55 | return nil, err |
| 53 | } | 56 | } |
| ... | @@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { | ... | @@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { |
| 56 | return x, nil | 59 | return x, nil |
| 57 | } | 60 | } |
| 58 | 61 | ||
| 59 | func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { | ||
| 60 | // Save memory data to temporary file | ||
| 61 | tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) | ||
| 62 | os.MkdirAll(path.Dir(tmpName), os.ModePerm) | ||
| 63 | if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { | ||
| 64 | return nil, err | ||
| 65 | } | ||
| 66 | return js.Parse(tmpName) | ||
| 67 | } | ||
| 68 | |||
| 69 | // A Config represents the json configuration. | 62 | // A Config represents the json configuration. |
| 70 | // Only when get value, support key as section:name type. | 63 | // Only when get value, support key as section:name type. |
| 71 | type JsonConfigContainer struct { | 64 | type JsonConfigContainer struct { |
| ... | @@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) { | ... | @@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) { |
| 88 | // DefaultBool return the bool value if has no error | 81 | // DefaultBool return the bool value if has no error |
| 89 | // otherwise return the defaultval | 82 | // otherwise return the defaultval |
| 90 | func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { | 83 | func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { |
| 91 | if v, err := c.Bool(key); err != nil { | 84 | if v, err := c.Bool(key); err == nil { |
| 92 | return defaultval | ||
| 93 | } else { | ||
| 94 | return v | 85 | return v |
| 95 | } | 86 | } |
| 87 | return defaultval | ||
| 96 | } | 88 | } |
| 97 | 89 | ||
| 98 | // Int returns the integer value for a given key. | 90 | // Int returns the integer value for a given key. |
| ... | @@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) { | ... | @@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) { |
| 110 | // DefaultInt returns the integer value for a given key. | 102 | // DefaultInt returns the integer value for a given key. |
| 111 | // if err != nil return defaltval | 103 | // if err != nil return defaltval |
| 112 | func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { | 104 | func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { |
| 113 | if v, err := c.Int(key); err != nil { | 105 | if v, err := c.Int(key); err == nil { |
| 114 | return defaultval | ||
| 115 | } else { | ||
| 116 | return v | 106 | return v |
| 117 | } | 107 | } |
| 108 | return defaultval | ||
| 118 | } | 109 | } |
| 119 | 110 | ||
| 120 | // Int64 returns the int64 value for a given key. | 111 | // Int64 returns the int64 value for a given key. |
| ... | @@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) { | ... | @@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) { |
| 132 | // DefaultInt64 returns the int64 value for a given key. | 123 | // DefaultInt64 returns the int64 value for a given key. |
| 133 | // if err != nil return defaltval | 124 | // if err != nil return defaltval |
| 134 | func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | 125 | func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { |
| 135 | if v, err := c.Int64(key); err != nil { | 126 | if v, err := c.Int64(key); err == nil { |
| 136 | return defaultval | ||
| 137 | } else { | ||
| 138 | return v | 127 | return v |
| 139 | } | 128 | } |
| 129 | return defaultval | ||
| 140 | } | 130 | } |
| 141 | 131 | ||
| 142 | // Float returns the float value for a given key. | 132 | // Float returns the float value for a given key. |
| ... | @@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) { | ... | @@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) { |
| 154 | // DefaultFloat returns the float64 value for a given key. | 144 | // DefaultFloat returns the float64 value for a given key. |
| 155 | // if err != nil return defaltval | 145 | // if err != nil return defaltval |
| 156 | func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | 146 | func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { |
| 157 | if v, err := c.Float(key); err != nil { | 147 | if v, err := c.Float(key); err == nil { |
| 158 | return defaultval | ||
| 159 | } else { | ||
| 160 | return v | 148 | return v |
| 161 | } | 149 | } |
| 150 | return defaultval | ||
| 162 | } | 151 | } |
| 163 | 152 | ||
| 164 | // String returns the string value for a given key. | 153 | // String returns the string value for a given key. |
| ... | @@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string { | ... | @@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string { |
| 175 | // DefaultString returns the string value for a given key. | 164 | // DefaultString returns the string value for a given key. |
| 176 | // if err != nil return defaltval | 165 | // if err != nil return defaltval |
| 177 | func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { | 166 | func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { |
| 178 | if v := c.String(key); v == "" { | 167 | // TODO FIXME should not use "" to replace non existance |
| 179 | return defaultval | 168 | if v := c.String(key); v != "" { |
| 180 | } else { | ||
| 181 | return v | 169 | return v |
| 182 | } | 170 | } |
| 171 | return defaultval | ||
| 183 | } | 172 | } |
| 184 | 173 | ||
| 185 | // Strings returns the []string value for a given key. | 174 | // Strings returns the []string value for a given key. |
| 186 | func (c *JsonConfigContainer) Strings(key string) []string { | 175 | func (c *JsonConfigContainer) Strings(key string) []string { |
| 176 | stringVal := c.String(key) | ||
| 177 | if stringVal == "" { | ||
| 178 | return []string{} | ||
| 179 | } | ||
| 187 | return strings.Split(c.String(key), ";") | 180 | return strings.Split(c.String(key), ";") |
| 188 | } | 181 | } |
| 189 | 182 | ||
| 190 | // DefaultStrings returns the []string value for a given key. | 183 | // DefaultStrings returns the []string value for a given key. |
| 191 | // if err != nil return defaltval | 184 | // if err != nil return defaltval |
| 192 | func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { | 185 | func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { |
| 193 | if v := c.Strings(key); len(v) == 0 { | 186 | if v := c.Strings(key); len(v) > 0 { |
| 194 | return defaultval | ||
| 195 | } else { | ||
| 196 | return v | 187 | return v |
| 197 | } | 188 | } |
| 189 | return defaultval | ||
| 198 | } | 190 | } |
| 199 | 191 | ||
| 200 | // GetSection returns map for the given section | 192 | // GetSection returns map for the given section |
| 201 | func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { | 193 | func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { |
| 202 | if v, ok := c.data[section]; ok { | 194 | if v, ok := c.data[section]; ok { |
| 203 | return v.(map[string]string), nil | 195 | return v.(map[string]string), nil |
| 204 | } else { | ||
| 205 | return nil, errors.New("not exist setction") | ||
| 206 | } | 196 | } |
| 197 | return nil, errors.New("nonexist section " + section) | ||
| 207 | } | 198 | } |
| 208 | 199 | ||
| 209 | // SaveConfigFile save the config into file | 200 | // SaveConfigFile save the config into file |
| ... | @@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { | ... | @@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { |
| 222 | return err | 213 | return err |
| 223 | } | 214 | } |
| 224 | 215 | ||
| 225 | // WriteValue writes a new value for key. | 216 | // Set writes a new value for key. |
| 226 | func (c *JsonConfigContainer) Set(key, val string) error { | 217 | func (c *JsonConfigContainer) Set(key, val string) error { |
| 227 | c.Lock() | 218 | c.Lock() |
| 228 | defer c.Unlock() | 219 | defer c.Unlock() |
| ... | @@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { | ... | @@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { |
| 241 | 232 | ||
| 242 | // section.key or key | 233 | // section.key or key |
| 243 | func (c *JsonConfigContainer) getData(key string) interface{} { | 234 | func (c *JsonConfigContainer) getData(key string) interface{} { |
| 244 | c.RLock() | ||
| 245 | defer c.RUnlock() | ||
| 246 | if len(key) == 0 { | 235 | if len(key) == 0 { |
| 247 | return nil | 236 | return nil |
| 248 | } | 237 | } |
| 249 | sectionKey := strings.Split(key, "::") | 238 | |
| 250 | if len(sectionKey) >= 2 { | 239 | c.RLock() |
| 251 | curValue, ok := c.data[sectionKey[0]] | 240 | defer c.RUnlock() |
| 241 | |||
| 242 | sectionKeys := strings.Split(key, "::") | ||
| 243 | if len(sectionKeys) >= 2 { | ||
| 244 | curValue, ok := c.data[sectionKeys[0]] | ||
| 252 | if !ok { | 245 | if !ok { |
| 253 | return nil | 246 | return nil |
| 254 | } | 247 | } |
| 255 | for _, key := range sectionKey[1:] { | 248 | for _, key := range sectionKeys[1:] { |
| 256 | if v, ok := curValue.(map[string]interface{}); ok { | 249 | if v, ok := curValue.(map[string]interface{}); ok { |
| 257 | if curValue, ok = v[key]; !ok { | 250 | if curValue, ok = v[key]; !ok { |
| 258 | return nil | 251 | return nil | ... | ... |
| ... | @@ -21,6 +21,7 @@ import ( | ... | @@ -21,6 +21,7 @@ import ( |
| 21 | 21 | ||
| 22 | var jsoncontext = `{ | 22 | var jsoncontext = `{ |
| 23 | "appname": "beeapi", | 23 | "appname": "beeapi", |
| 24 | "testnames": "foo;bar", | ||
| 24 | "httpport": 8080, | 25 | "httpport": 8080, |
| 25 | "mysqlport": 3600, | 26 | "mysqlport": 3600, |
| 26 | "PI": 3.1415976, | 27 | "PI": 3.1415976, |
| ... | @@ -28,8 +29,8 @@ var jsoncontext = `{ | ... | @@ -28,8 +29,8 @@ var jsoncontext = `{ |
| 28 | "autorender": false, | 29 | "autorender": false, |
| 29 | "copyrequestbody": true, | 30 | "copyrequestbody": true, |
| 30 | "database": { | 31 | "database": { |
| 31 | "host": "host", | 32 | "host": "host", |
| 32 | "port": "port", | 33 | "port": "port", |
| 33 | "database": "database", | 34 | "database": "database", |
| 34 | "username": "username", | 35 | "username": "username", |
| 35 | "password": "password", | 36 | "password": "password", |
| ... | @@ -122,6 +123,12 @@ func TestJson(t *testing.T) { | ... | @@ -122,6 +123,12 @@ func TestJson(t *testing.T) { |
| 122 | if jsonconf.String("runmode") != "dev" { | 123 | if jsonconf.String("runmode") != "dev" { |
| 123 | t.Fatal("runmode not equal to dev") | 124 | t.Fatal("runmode not equal to dev") |
| 124 | } | 125 | } |
| 126 | if v := jsonconf.Strings("unknown"); len(v) > 0 { | ||
| 127 | t.Fatal("unknown strings, the length should be 0") | ||
| 128 | } | ||
| 129 | if v := jsonconf.Strings("testnames"); len(v) != 2 { | ||
| 130 | t.Fatal("testnames length should be 2") | ||
| 131 | } | ||
| 125 | if v, err := jsonconf.Bool("autorender"); err != nil || v != false { | 132 | if v, err := jsonconf.Bool("autorender"); err != nil || v != false { |
| 126 | t.Error(v) | 133 | t.Error(v) |
| 127 | t.Fatal(err) | 134 | t.Fatal(err) |
| ... | @@ -179,4 +186,8 @@ func TestJson(t *testing.T) { | ... | @@ -179,4 +186,8 @@ func TestJson(t *testing.T) { |
| 179 | if _, err := jsonconf.Bool("unknown"); err == nil { | 186 | if _, err := jsonconf.Bool("unknown"); err == nil { |
| 180 | t.Error("unknown keys should return an error when expecting a Bool") | 187 | t.Error("unknown keys should return an error when expecting a Bool") |
| 181 | } | 188 | } |
| 189 | |||
| 190 | if !jsonconf.DefaultBool("unknow", true) { | ||
| 191 | t.Error("unknown keys with default value wrong") | ||
| 192 | } | ||
| 182 | } | 193 | } | ... | ... |
-
Please register or sign in to post a comment