mirror of
https://github.com/gogf/gf.git
synced 2025-04-05 11:18:50 +08:00
add support for .properties configuration file
This commit is contained in:
parent
32f33b9f8c
commit
7198eb3b66
@ -22,13 +22,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ContentTypeJson = `json`
|
||||
ContentTypeJs = `js`
|
||||
ContentTypeXml = `xml`
|
||||
ContentTypeIni = `ini`
|
||||
ContentTypeYaml = `yaml`
|
||||
ContentTypeYml = `yml`
|
||||
ContentTypeToml = `toml`
|
||||
ContentTypeJson = `json`
|
||||
ContentTypeJs = `js`
|
||||
ContentTypeXml = `xml`
|
||||
ContentTypeIni = `ini`
|
||||
ContentTypeYaml = `yaml`
|
||||
ContentTypeYml = `yml`
|
||||
ContentTypeToml = `toml`
|
||||
ContentTypeProperties = `properties`
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -8,6 +8,7 @@ package gjson
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/encoding/gini"
|
||||
"github.com/gogf/gf/v2/encoding/gproperties"
|
||||
"github.com/gogf/gf/v2/encoding/gtoml"
|
||||
"github.com/gogf/gf/v2/encoding/gxml"
|
||||
"github.com/gogf/gf/v2/encoding/gyaml"
|
||||
@ -197,3 +198,30 @@ func (j *Json) MustToIni() []byte {
|
||||
func (j *Json) MustToIniString() string {
|
||||
return string(j.MustToIni())
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// properties
|
||||
// ========================================================================
|
||||
// Toproperties json to properties
|
||||
func (j *Json) ToProperties() ([]byte, error) {
|
||||
return gproperties.Encode(j.Map())
|
||||
}
|
||||
|
||||
// TopropertiesString properties to string
|
||||
func (j *Json) ToPropertiesString() (string, error) {
|
||||
b, e := j.ToProperties()
|
||||
return string(b), e
|
||||
}
|
||||
|
||||
func (j *Json) MustToProperties() []byte {
|
||||
result, err := j.ToProperties()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MustTopropertiesString
|
||||
func (j *Json) MustToPropertiesString() string {
|
||||
return string(j.MustToProperties())
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gini"
|
||||
"github.com/gogf/gf/v2/encoding/gproperties"
|
||||
"github.com/gogf/gf/v2/encoding/gtoml"
|
||||
"github.com/gogf/gf/v2/encoding/gxml"
|
||||
"github.com/gogf/gf/v2/encoding/gyaml"
|
||||
@ -288,6 +289,10 @@ func doLoadContentWithOptions(data []byte, options Options) (*Json, error) {
|
||||
if data, err = gini.ToJson(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ContentTypeProperties:
|
||||
if data, err = gproperties.ToJson(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
err = gerror.NewCodef(
|
||||
@ -335,6 +340,8 @@ func checkDataType(content []byte) string {
|
||||
(gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, content) || gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content)) {
|
||||
// Must contain "[xxx]" section.
|
||||
return ContentTypeIni
|
||||
} else if gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content) {
|
||||
return ContentTypeProperties
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
176
encoding/gproperties/gproperties.go
Normal file
176
encoding/gproperties/gproperties.go
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gproperties provides accessing and converting for .properties content.
|
||||
|
||||
package gproperties
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/json"
|
||||
)
|
||||
|
||||
func genMap(m map[string]interface{}, keys []string, value interface{}) (err error) {
|
||||
if m == nil {
|
||||
m = make(map[string]interface{})
|
||||
}
|
||||
if len(keys) == 1 {
|
||||
m[keys[0]] = value
|
||||
} else {
|
||||
if m[keys[0]] == nil {
|
||||
m[keys[0]] = make(map[string]interface{})
|
||||
}
|
||||
if _, ok := m[keys[0]].(map[string]interface{}); ok == false {
|
||||
err = gerror.Wrapf(gerror.New(".properties data format error"), `.properties data format error`)
|
||||
return
|
||||
}
|
||||
err = genMap(m[keys[0]].(map[string]interface{}), keys[1:], value)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Decode converts properties format to map.
|
||||
func Decode(data []byte) (res map[string]interface{}, err error) {
|
||||
res = make(map[string]interface{})
|
||||
var (
|
||||
m = make(map[string]interface{})
|
||||
bytesReader = bytes.NewReader(data)
|
||||
bufioReader = bufio.NewReader(bytesReader)
|
||||
line string
|
||||
)
|
||||
|
||||
for {
|
||||
line, err = bufioReader.ReadString('\n')
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
err = gerror.Wrapf(err, `bufioReader.ReadString failed`)
|
||||
return nil, err
|
||||
}
|
||||
if line = strings.TrimSpace(line); len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if line[0] == ';' || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(line, "=") {
|
||||
values := strings.Split(line, "=")
|
||||
m[strings.TrimSpace(values[0])] = strings.TrimSpace(strings.Join(values[1:], "="))
|
||||
}
|
||||
}
|
||||
|
||||
//[0][name] replace to .0.name
|
||||
|
||||
for k, v := range m {
|
||||
keys := strings.Split(strings.ReplaceAll(strings.ReplaceAll(k, "[", "."), "]", ""), ".")
|
||||
genMap(res, keys, v)
|
||||
}
|
||||
//.properties is not support array officially
|
||||
return res, nil
|
||||
}
|
||||
func point(base string) string {
|
||||
if len(strings.TrimSpace(base)) > 0 {
|
||||
return "."
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func arrayToProperties(data []interface{}, w *bytes.Buffer, base string) (err error) {
|
||||
for i, value := range data {
|
||||
switch t := value.(type) {
|
||||
//the basic types
|
||||
case bool, uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64, string, nil:
|
||||
{
|
||||
n, err := w.WriteString(fmt.Sprintf("%s%s%d=%v\n", base, point(base), i, value))
|
||||
if err != nil || n == 0 {
|
||||
return gerror.Wrapf(err, "w.WriteString failed")
|
||||
}
|
||||
}
|
||||
break
|
||||
//array
|
||||
case []interface{}:
|
||||
if err = arrayToProperties(value.([]interface{}), w, fmt.Sprintf("%s%s%v", base, point(base), i)); err != nil {
|
||||
return
|
||||
}
|
||||
break
|
||||
//object
|
||||
case map[string]interface{}:
|
||||
if err = toProperties(value.(map[string]interface{}), w, fmt.Sprintf("%s%s%d", base, point(base), i)); err != nil {
|
||||
return
|
||||
}
|
||||
break
|
||||
default:
|
||||
return gerror.Wrapf(err, fmt.Sprintf("data type not support %v", t))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func toProperties(data map[string]interface{}, w *bytes.Buffer, base string) (err error) {
|
||||
for key, value := range data {
|
||||
switch t := value.(type) {
|
||||
//base types
|
||||
case bool, uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64, float32, float64, string, nil:
|
||||
{
|
||||
n, err := w.WriteString(fmt.Sprintf("%s%s%s=%v\n", base, point(base), key, value))
|
||||
if err != nil || n == 0 {
|
||||
return gerror.Wrapf(err, "w.WriteString failed")
|
||||
}
|
||||
}
|
||||
break
|
||||
//array
|
||||
case []interface{}:
|
||||
if err = arrayToProperties(value.([]interface{}), w, fmt.Sprintf("%s%s%v", base, point(base), key)); err != nil {
|
||||
return
|
||||
}
|
||||
break
|
||||
//object
|
||||
case map[string]interface{}:
|
||||
if err = toProperties(value.(map[string]interface{}), w, fmt.Sprintf("%s%s%s", base, point(base), key)); err != nil {
|
||||
return
|
||||
}
|
||||
break
|
||||
default:
|
||||
return gerror.Wrapf(err, fmt.Sprintf("data type not support %v", t))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Encode converts map to properties format.
|
||||
func Encode(data map[string]interface{}) (res []byte, err error) {
|
||||
var (
|
||||
w = new(bytes.Buffer)
|
||||
)
|
||||
err = toProperties(data, w, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res = make([]byte, w.Len())
|
||||
if n, err := w.Read(res); err != nil || n == 0 {
|
||||
return nil, gerror.Wrapf(err, "w.Read failed")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ToJson convert .properties format to JSON.
|
||||
func ToJson(data []byte) (res []byte, err error) {
|
||||
iniMap, err := Decode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(iniMap)
|
||||
}
|
53
encoding/gproperties/gproperties_z_unit_test.go
Normal file
53
encoding/gproperties/gproperties_z_unit_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package gproperties_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gproperties"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
var pStr string = `
|
||||
# template
|
||||
data = "/home/www/templates/"
|
||||
# MySQL
|
||||
sql.disk.0 = 127.0.0.1:6379,0
|
||||
sql.cache.0 = 127.0.0.1:6379,1=
|
||||
sql.cache.1=0
|
||||
sql.disk.a = 10
|
||||
`
|
||||
|
||||
func TestDecode(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
|
||||
decodeStr, err := gproperties.Decode(([]byte)(pStr))
|
||||
if err != nil {
|
||||
t.Errorf("decode failed. %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v\n", decodeStr)
|
||||
v, _ := json.Marshal(decodeStr)
|
||||
fmt.Printf("%v\n", string(v))
|
||||
})
|
||||
}
|
||||
func TestEncode(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
|
||||
decodeStr, err := gproperties.Encode(map[string]interface{}{
|
||||
"sql": g.Map{
|
||||
"userName": "admin",
|
||||
"password": "123456",
|
||||
},
|
||||
"user": g.Slice{"admin", "aa"},
|
||||
"no": 123,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("decode failed. %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v\n", string(decodeStr))
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user