github.com/eframework-cn/EP.GO.UTIL@v1.0.0/xconfig/json.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package xconfig 16 17 import ( 18 "encoding/json" 19 "errors" 20 "fmt" 21 "io/ioutil" 22 "os" 23 "strings" 24 "sync" 25 ) 26 27 // JSONConfig is a json config parser and implements Config interface. 28 type JSONConfig struct { 29 } 30 31 // Parse returns a ConfigContainer with parsed json config map. 32 func (js *JSONConfig) Parse(filename string) (Configer, error) { 33 file, err := os.Open(filename) 34 if err != nil { 35 return nil, err 36 } 37 defer file.Close() 38 content, err := ioutil.ReadAll(file) 39 if err != nil { 40 return nil, err 41 } 42 43 return js.ParseData(content) 44 } 45 46 // ParseData returns a ConfigContainer with json string 47 func (js *JSONConfig) ParseData(data []byte) (Configer, error) { 48 x := &JSONConfigContainer{ 49 data: make(map[string]interface{}), 50 } 51 err := json.Unmarshal(data, &x.data) 52 if err != nil { 53 var wrappingArray []interface{} 54 err2 := json.Unmarshal(data, &wrappingArray) 55 if err2 != nil { 56 return nil, err 57 } 58 x.data["rootArray"] = wrappingArray 59 } 60 61 x.data = ExpandValueEnvForMap(x.data) 62 63 return x, nil 64 } 65 66 // JSONConfigContainer A Config represents the json configuration. 67 // Only when get value, support key as section:name type. 68 type JSONConfigContainer struct { 69 data map[string]interface{} 70 sync.RWMutex 71 } 72 73 // Bool returns the boolean value for a given key. 74 func (c *JSONConfigContainer) Bool(key string) (bool, error) { 75 val := c.getData(key) 76 if val != nil { 77 return ParseBool(val) 78 } 79 return false, fmt.Errorf("not exist key: %q", key) 80 } 81 82 // DefaultBool return the bool value if has no error 83 // otherwise return the defaultval 84 func (c *JSONConfigContainer) DefaultBool(key string, defaultval bool) bool { 85 if v, err := c.Bool(key); err == nil { 86 return v 87 } 88 return defaultval 89 } 90 91 // Int returns the integer value for a given key. 92 func (c *JSONConfigContainer) Int(key string) (int, error) { 93 val := c.getData(key) 94 if val != nil { 95 if v, ok := val.(float64); ok { 96 return int(v), nil 97 } 98 return 0, errors.New("not int value") 99 } 100 return 0, errors.New("not exist key:" + key) 101 } 102 103 // DefaultInt returns the integer value for a given key. 104 // if err != nil return defaultval 105 func (c *JSONConfigContainer) DefaultInt(key string, defaultval int) int { 106 if v, err := c.Int(key); err == nil { 107 return v 108 } 109 return defaultval 110 } 111 112 // Int64 returns the int64 value for a given key. 113 func (c *JSONConfigContainer) Int64(key string) (int64, error) { 114 val := c.getData(key) 115 if val != nil { 116 if v, ok := val.(float64); ok { 117 return int64(v), nil 118 } 119 return 0, errors.New("not int64 value") 120 } 121 return 0, errors.New("not exist key:" + key) 122 } 123 124 // DefaultInt64 returns the int64 value for a given key. 125 // if err != nil return defaultval 126 func (c *JSONConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 127 if v, err := c.Int64(key); err == nil { 128 return v 129 } 130 return defaultval 131 } 132 133 // Float returns the float value for a given key. 134 func (c *JSONConfigContainer) Float(key string) (float64, error) { 135 val := c.getData(key) 136 if val != nil { 137 if v, ok := val.(float64); ok { 138 return v, nil 139 } 140 return 0.0, errors.New("not float64 value") 141 } 142 return 0.0, errors.New("not exist key:" + key) 143 } 144 145 // DefaultFloat returns the float64 value for a given key. 146 // if err != nil return defaultval 147 func (c *JSONConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 148 if v, err := c.Float(key); err == nil { 149 return v 150 } 151 return defaultval 152 } 153 154 // String returns the string value for a given key. 155 func (c *JSONConfigContainer) String(key string) string { 156 val := c.getData(key) 157 if val != nil { 158 if v, ok := val.(string); ok { 159 return v 160 } 161 } 162 return "" 163 } 164 165 // DefaultString returns the string value for a given key. 166 // if err != nil return defaultval 167 func (c *JSONConfigContainer) DefaultString(key string, defaultval string) string { 168 // TODO FIXME should not use "" to replace non existence 169 if v := c.String(key); v != "" { 170 return v 171 } 172 return defaultval 173 } 174 175 // Strings returns the []string value for a given key. 176 func (c *JSONConfigContainer) Strings(key string) []string { 177 stringVal := c.String(key) 178 if stringVal == "" { 179 return nil 180 } 181 return strings.Split(c.String(key), ";") 182 } 183 184 // DefaultStrings returns the []string value for a given key. 185 // if err != nil return defaultval 186 func (c *JSONConfigContainer) DefaultStrings(key string, defaultval []string) []string { 187 if v := c.Strings(key); v != nil { 188 return v 189 } 190 return defaultval 191 } 192 193 // GetSection returns map for the given section 194 func (c *JSONConfigContainer) GetSection(section string) (map[string]string, error) { 195 if v, ok := c.data[section]; ok { 196 return v.(map[string]string), nil 197 } 198 return nil, errors.New("nonexist section " + section) 199 } 200 201 // SaveConfigFile save the config into file 202 func (c *JSONConfigContainer) SaveConfigFile(filename string) (err error) { 203 // Write configuration file by filename. 204 f, err := os.Create(filename) 205 if err != nil { 206 return err 207 } 208 defer f.Close() 209 b, err := json.MarshalIndent(c.data, "", " ") 210 if err != nil { 211 return err 212 } 213 _, err = f.Write(b) 214 return err 215 } 216 217 // Set writes a new value for key. 218 func (c *JSONConfigContainer) Set(key, val string) error { 219 c.Lock() 220 defer c.Unlock() 221 c.data[key] = val 222 return nil 223 } 224 225 // DIY returns the raw value by a given key. 226 func (c *JSONConfigContainer) DIY(key string) (v interface{}, err error) { 227 val := c.getData(key) 228 if val != nil { 229 return val, nil 230 } 231 return nil, errors.New("not exist key") 232 } 233 234 // section.key or key 235 func (c *JSONConfigContainer) getData(key string) interface{} { 236 if len(key) == 0 { 237 return nil 238 } 239 240 c.RLock() 241 defer c.RUnlock() 242 243 sectionKeys := strings.Split(key, "::") 244 if len(sectionKeys) >= 2 { 245 curValue, ok := c.data[sectionKeys[0]] 246 if !ok { 247 return nil 248 } 249 for _, key := range sectionKeys[1:] { 250 if v, ok := curValue.(map[string]interface{}); ok { 251 if curValue, ok = v[key]; !ok { 252 return nil 253 } 254 } 255 } 256 return curValue 257 } 258 if v, ok := c.data[key]; ok { 259 return v 260 } 261 return nil 262 } 263 264 func init() { 265 Register("json", &JSONConfig{}) 266 }