From 5dab00fddb519919409843259021e216f688a5f2 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 19 Jan 2018 15:26:28 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/encoding/gjson/gjson.go | 18 +- g/encoding/gjson/internal/gjson.go | 443 ----------------------------- g/encoding/gxml/gxml.go | 31 ++ g/frame/gcfg/gcfg.go | 28 +- geg/database/mysql/mysql.go | 4 +- geg/other/test.go | 50 +++- 6 files changed, 118 insertions(+), 456 deletions(-) delete mode 100644 g/encoding/gjson/internal/gjson.go create mode 100644 g/encoding/gxml/gxml.go diff --git a/g/encoding/gjson/gjson.go b/g/encoding/gjson/gjson.go index 98196ad34..96df83bf9 100644 --- a/g/encoding/gjson/gjson.go +++ b/g/encoding/gjson/gjson.go @@ -13,6 +13,9 @@ import ( "io/ioutil" "encoding/json" "gitee.com/johng/gf/g/util/gconv" + "gitee.com/johng/gf/g/os/gfile" + "errors" + "gitee.com/johng/gf/g/encoding/gxml" ) // json解析结果存放数组 @@ -39,7 +42,7 @@ func Decode (b []byte) (interface{}, error) { } } -// 解析json字符串为go变量,注意第二个参数为指针 +// 解析json字符串为go变量,注意第二个参数为指针(任意结构的变量) func DecodeTo (b []byte, v interface{}) error { return json.Unmarshal(b, v) } @@ -53,13 +56,22 @@ func DecodeToJson (b []byte) (*Json, error) { } } -// 加载json文件内容,并转换为json对象 +// 支持多种配置文件类型转换为json格式内容并解析为gjson.Json对象 +// 支持的配置文件格式:xml, json, yml func Load (path string) (*Json, error) { + var result interface{} data, err := ioutil.ReadFile(path) if err != nil { return nil, err } - var result interface{} + switch gfile.Ext(path) { + case ".xml": + data, err = gxml.ToJson(data) + if err != nil { + return nil, err + } + case ".yml": + } if err := json.Unmarshal(data, &result); err != nil { return nil, err } diff --git a/g/encoding/gjson/internal/gjson.go b/g/encoding/gjson/internal/gjson.go deleted file mode 100644 index 362fa1a17..000000000 --- a/g/encoding/gjson/internal/gjson.go +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright 2017 gf Author(https://gitee.com/johng/gf). 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://gitee.com/johng/gf. - - -package internal - -import ( - "fmt" - "errors" - "strings" - "strconv" -) - -// 这是一个自己开发的,使用go进行json语法解析的解析器,效率没有官方的json解析高,仅作学习参考 - -const ( - gJSON_CHAR_BRACE_LEFT = rune('{') - gJSON_CHAR_BRACE_RIGHT = rune('}') - gJSON_CHAR_BRACKET_LEFT = rune('[') - gJSON_CHAR_BRACKET_RIGHT = rune(']') - gJSON_CHAR_QUOTATION = rune('\\') - gJSON_CHAR_COMMA = rune(',') - gJSON_CHAR_COLON = rune(':') - gJSON_CHAR_DOUBLE_QUOTE_MARK = rune('"') -) - -const ( - gJSON_TOKEN_BRACE_LEFT = rune('{') - gJSON_TOKEN_BRACE_RIGHT = rune('}') - gJSON_TOKEN_BRACKET_LEFT = rune('[') - gJSON_TOKEN_BRACKET_RIGHT = rune(']') - gJSON_TOKEN_COMMA = rune(',') - gJSON_TOKEN_COLON = rune(':') - gJSON_TOKEN_STRING = rune('"') - gJSON_TOKEN_NUMBER = rune('0') -) - -// json关联数组(哈希表) -type JsonMap map[string]interface{} -// json索引数组(普通数组,从0开始索引) -type JsonArray []interface{} - -// JSON数据对象 -type gJsonNode struct { - m JsonMap - a JsonArray -} - -// JSON语义token -type gJsonToken struct { - token []rune // token字符串 - tokenType rune // token类型 - tokenindex int // token在原始字符串中的索引位置 -} - -// JSON解析结构对象 -type gJsonParser struct { - content []rune // 需要解析json字符串(通过string转换为[]rune) - tokens []gJsonToken // 存放解析content后的json token数组 - root *gJsonNode // json根节点 - pointer *gJsonNode // 指向当前正在解析的json节点 -} - -// 解析json字符串 -func Decode(j *string) (*gJsonParser, error) { - p := &gJsonParser{content:[]rune(*j)} - err := p.parse() - if err == nil { - return p, err - } else { - return nil, err - } -} - -// 判断所给字符串是否为数字 -func isNumeric(s string) bool { - for i :=0; i < len(s); i++ { - if s[i] < byte('0') || s[i] > byte('9') { - return false - } - } - return true -} - -// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换 -// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil -func (p *gJsonParser) GetMap(pattern string) JsonMap { - result := p.Get(pattern) - if result != nil { - if r, ok := result.(JsonMap); ok { - return r - } - } - return nil -} - -// 获得一个数组[]interface{},方便操作,不需要自己做类型转换 -// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil -func (p *gJsonParser) GetArray(pattern string) JsonArray { - result := p.Get(pattern) - if result != nil { - if r, ok := result.(JsonArray); ok { - return r - } - } - return nil -} - - -// 根据约定字符串方式访问json解析数据,参数形如: "items.name.first", "list.0" -// 返回的结果类型的interface{},因此需要自己做类型转换 -// 如果找不到对应节点的数据,返回nil -func (p *gJsonParser) Get(pattern string) interface{} { - var result interface{} - pointer := p.root - array := strings.Split(pattern, ".") - length := len(array) - for i:= 0; i < length; i++ { - // 优先判断数组 - if isNumeric(array[i]) { - n, err := strconv.Atoi(array[i]) - if err == nil && len(pointer.a) > n { - if i == length - 1 { - result = pointer.a[n] - break; - } else { - if p, ok := pointer.a[n].(*gJsonNode); ok { - pointer = p - continue - } - } - } - } - // 其次判断哈希表,如果一个键在数组及map中均不存在,直接返回nil - if v, ok := pointer.m[array[i]]; ok { - if i == length - 1 { - result = v - } else { - if p, ok := v.(*gJsonNode); ok { - pointer = p - continue - } - } - } else { - return nil - } - } - // 处理结果,如果是gJsonNode类型,那么需要做转换 - if r, ok := result.(*gJsonNode); ok { - if len(r.m) < 1 { - return r.a - } else { - return r.m - } - } - return result -} - -// 遍历json字符串数组,并且判断转义 -func (p *gJsonParser) getNextChar(c rune, f int) int { - for i := f + 1; i < len(p.content); i++ { - if p.content[i] == c { - if i > 0 && p.content[i - 1] != gJSON_CHAR_QUOTATION { - return i - } - } else { - switch p.content[i] { - case gJSON_CHAR_DOUBLE_QUOTE_MARK: - r := p.getNextChar(gJSON_CHAR_DOUBLE_QUOTE_MARK, i) - if r > 0 { - i = r - } - } - } - } - return 0 -} - -// 判断字符是否为数字 -func (p *gJsonParser) isCharNumber(c rune) bool { - if c >= rune('0') && c <= rune('9') { - return true - } - return false -} - -// 按照json语法对保存的字符串进行解析 -func (p *gJsonParser) parse() error { - // 首先将字符串解析成token进行保存 - for i := 0; i < len(p.content); i++ { - if p.isCharNumber(p.content[i]) { - j := i + 1 - for ; j < len(p.content); j++ { - if !p.isCharNumber(p.content[j]) { - break; - } - } - p.tokens = append(p.tokens, gJsonToken { - token: p.content[i:j], - tokenType: gJSON_TOKEN_NUMBER, - tokenindex: i, - }) - i = j - 1 - } else { - switch p.content[i] { - case gJSON_CHAR_DOUBLE_QUOTE_MARK: - r := p.getNextChar(gJSON_CHAR_DOUBLE_QUOTE_MARK, i) - if r > 0 { - // 注意这里需要去掉字符串两边的双引号 - p.tokens = append(p.tokens, gJsonToken { - token: p.content[i+1:r], - tokenType: gJSON_TOKEN_STRING, - tokenindex: i, - }) - i = r - } - case gJSON_CHAR_COLON: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_COLON, tokenindex: i}) - case gJSON_CHAR_COMMA: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_COMMA, tokenindex: i}) - case gJSON_CHAR_BRACE_LEFT: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACE_LEFT, tokenindex: i}) - case gJSON_CHAR_BRACE_RIGHT: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACE_RIGHT, tokenindex: i}) - case gJSON_CHAR_BRACKET_LEFT: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACKET_LEFT, tokenindex: i}) - case gJSON_CHAR_BRACKET_RIGHT: - p.tokens = append(p.tokens, gJsonToken{token: p.content[i:i+1], tokenType: gJSON_TOKEN_BRACKET_RIGHT, tokenindex: i}) - - default: - c := string(p.content[i]) - if c != " " && c != "\r" && c != "\n" && c != "\t" { - return errors.New(fmt.Sprintf("json parse error: invalid char '%s' at index %d", c, i)) - } - } - } - } - // 最后对解析后的token转换为go变量 - return p.parseTokenNodeToVar(0, len(p.tokens) - 1) -} - -// 获取json范围字符包含范围最右侧的索引位置 -func (p *gJsonParser)getTokenBorderRightIndex(token rune, from int) int { - switch token { - case gJSON_TOKEN_BRACE_LEFT: - leftCount := 0 - for i := from + 1; i < len(p.tokens); i++ { - if p.tokens[i].tokenType == gJSON_TOKEN_BRACE_LEFT { - leftCount ++ - } else if p.tokens[i].tokenType == gJSON_TOKEN_BRACE_RIGHT { - if leftCount < 1 { - return i - } else { - leftCount-- - } - } - } - case gJSON_CHAR_BRACKET_LEFT: - leftCount := 0 - for i := from + 1; i < len(p.tokens); i++ { - if p.tokens[i].tokenType == gJSON_CHAR_BRACKET_LEFT { - leftCount ++ - } else if p.tokens[i].tokenType == gJSON_CHAR_BRACKET_RIGHT { - if leftCount < 1 { - return i - } else { - leftCount-- - } - } - } - } - return 0 -} - -// 将解析过后的json token转换为go变量 -func (p *gJsonParser) parseTokenNodeToVar(left int, right int) error { - //fmt.Println("================================") - //for i := left; i <= right; i++ { - // fmt.Println(string(p.tokens[i].token)) - //} - for i := left; i <= right; i++ { - //fmt.Println(string(p.tokens[i].token)) - switch p.tokens[i].tokenType { - case gJSON_TOKEN_BRACE_LEFT: - fallthrough - case gJSON_TOKEN_BRACKET_LEFT: - node := newJsonNode() - // 判断根节点 - if p.root == nil { - p.root = node - p.pointer = node - } - // 判断层级关系 - borderRight := p.getTokenBorderRightIndex(p.tokens[i].tokenType, i) - if borderRight < 1 { - return errors.New(fmt.Sprintf("json parse error: unclosed tag '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex)) - } - if i > 1 && ( - p.tokens[i-1].tokenType == gJSON_TOKEN_COLON && - p.tokens[i-2].tokenType == gJSON_TOKEN_STRING) { - // json赋值操作 - oldptr := p.pointer - k := string(p.tokens[i-2].token) - p.pointer.m[k] = node - p.pointer = node - err := p.parseTokenNodeToVar(i + 1, borderRight - 1) - if err != nil { - return err - } else { - i = borderRight - p.pointer = oldptr - } - - } else if i > 0 && ( - p.tokens[i-1].tokenType == gJSON_TOKEN_COMMA || - p.tokens[i-1].tokenType == gJSON_TOKEN_BRACE_LEFT || - p.tokens[i-1].tokenType == gJSON_TOKEN_BRACKET_LEFT) { - // json数组操作 - oldptr := p.pointer - p.pointer.a = append(p.pointer.a, node) - p.pointer = node - err := p.parseTokenNodeToVar(i + 1, borderRight - 1) - if err != nil { - return err - } else { - i = borderRight - p.pointer = oldptr - } - } else { - // json层级关系 - p.pointer = node - err := p.parseTokenNodeToVar(i + 1, borderRight - 1) - if err != nil { - return err - } else { - i = borderRight - } - } - - case gJSON_TOKEN_STRING: - fallthrough - case gJSON_TOKEN_NUMBER: - if i > 0 && p.tokens[i-1].tokenType == gJSON_TOKEN_COLON { - k := string(p.tokens[i-2].token) - v := string(p.tokens[i].token) - p.pointer.m[k] = v - } else if p.tokens[i+1].tokenType != gJSON_TOKEN_COLON { - p.pointer.a = append(p.pointer.a, string(p.tokens[i].token)) - } - - case gJSON_TOKEN_COLON: - if i < 1 || (p.tokens[i-1].tokenType != gJSON_TOKEN_STRING) { - return errors.New(fmt.Sprintf("json parse error: invalid charactar '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex)) - } - - case gJSON_TOKEN_COMMA: - if (p.tokens[i+1].tokenType != gJSON_TOKEN_STRING && - p.tokens[i+1].tokenType != gJSON_TOKEN_NUMBER && - p.tokens[i+1].tokenType != gJSON_TOKEN_BRACE_LEFT && - p.tokens[i+1].tokenType != gJSON_TOKEN_BRACKET_LEFT) || - (i < 1 || ( - p.tokens[i-1].tokenType != gJSON_TOKEN_STRING && - p.tokens[i-1].tokenType != gJSON_TOKEN_NUMBER && - p.tokens[i-1].tokenType != gJSON_TOKEN_BRACE_RIGHT && - p.tokens[i-1].tokenType != gJSON_TOKEN_BRACKET_RIGHT)) { - return errors.New(fmt.Sprintf("json parse error: invalid charactar '%s' at index %d", string(p.tokens[i].token), p.tokens[i].tokenindex)) - } - } - } - return nil -} - -// 打印出所有的token(测试用) -func (p *gJsonParser)printTokens() { - for _, v := range p.tokens { - fmt.Println(string(v.token)) - } -} - -// 格式化打印根节点 -func (p *gJsonParser)Print() { - if len(p.root.m) > 0 { - fmt.Println("{") - } else { - fmt.Println("[") - } - p.printNode(p.pointer, "\t") - if len(p.root.m) > 0 { - fmt.Println("}") - } else { - fmt.Println("]") - } -} - -// 格式化打印根节点 -func (p *gJsonParser)printNode(n *gJsonNode, indent string) { - if len(n.m) > 0 { - for k, v := range n.m { - if t, ok := v.(*gJsonNode); ok { - if len(t.m) > 0 { - fmt.Printf("%v%v\t: {\n", indent, k) - p.printNode(t, indent + "\t") - fmt.Printf("%v}\n", indent) - } else { - fmt.Printf("%v%v\t: [\n", indent, k) - p.printNode(t, indent + "\t") - fmt.Printf("%v}\n", indent) - } - } else { - fmt.Printf("%v%v\t: %v\n", indent, k, v) - } - } - } - if len(n.a) > 0 { - for k, v := range n.a { - if t, ok := v.(*gJsonNode); ok { - if len(t.m) > 0 { - fmt.Printf("%v%v\t: {\n", indent, k) - p.printNode(t, indent + "\t") - fmt.Printf("%v}\n", indent) - } else { - fmt.Printf("%v%v\t: [\n", indent, k) - p.printNode(t, indent + "\t") - fmt.Printf("%v}\n", indent) - } - } else { - fmt.Printf("%v%v : %v\n", indent, k, v) - } - } - } -} - -// 创建一个json数据对象 -func newJsonNode() *gJsonNode { - return &gJsonNode { - m: make(map[string]interface{}), - a: make([]interface{}, 0), - } -} - diff --git a/g/encoding/gxml/gxml.go b/g/encoding/gxml/gxml.go new file mode 100644 index 000000000..b54b7916a --- /dev/null +++ b/g/encoding/gxml/gxml.go @@ -0,0 +1,31 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). 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://gitee.com/johng/gf. + +// XML +package gxml + +import ( + "github.com/clbanning/mxj" +) + +// 将XML内容解析为map变量 +func Decode(xmlbyte []byte) (map[string]interface{}, error) { + return mxj.NewMapXml(xmlbyte) +} + +// 将map变量解析为XML格式内容 +func Encode(v map[string]interface{}) ([]byte, error) { + return mxj.Map(v).Xml() +} + +// XML格式内容直接转换为JSON格式内容 +func ToJson(xmlbyte []byte) ([]byte, error) { + if mv, err := mxj.NewMapXml(xmlbyte); err == nil { + return mv.Json() + } else { + return nil, err + } +} \ No newline at end of file diff --git a/g/frame/gcfg/gcfg.go b/g/frame/gcfg/gcfg.go index 0c85405c8..aaef0f8f3 100644 --- a/g/frame/gcfg/gcfg.go +++ b/g/frame/gcfg/gcfg.go @@ -16,7 +16,7 @@ import ( ) const ( - gDEFAULT_CONFIG_FILE = "config" // 默认的配置管理文件名称 + gDEFAULT_CONFIG_FILE = "config.json" // 默认的配置管理文件名称 ) // 配置管理对象 @@ -43,7 +43,7 @@ func (c *Config) filePath(files []string) string { c.mu.RLock() fpath := c.path + gfile.Separator + file c.mu.RUnlock() - return fpath + ".json" + return fpath } // 设置配置管理器的配置文件存放目录绝对路径 @@ -111,6 +111,14 @@ func (c *Config) GetBool(pattern string, files...string) bool { return false } +// 返回指定json中的float32 +func (c *Config) GetFloat32(pattern string, files...string) float32 { + if j := c.getJson(files); j != nil { + return j.GetFloat32(pattern) + } + return 0 +} + // 返回指定json中的float64 func (c *Config) GetFloat64(pattern string, files...string) float64 { if j := c.getJson(files); j != nil { @@ -121,10 +129,16 @@ func (c *Config) GetFloat64(pattern string, files...string) float64 { // 返回指定json中的float64->int func (c *Config) GetInt(pattern string, files...string) int { - return int(c.GetFloat64(pattern)) + if j := c.getJson(files); j != nil { + return j.GetInt(pattern) + } + return 0 } -// 返回指定json中的float64->int64 -func (c *Config) GetInt64(pattern string, files...string) int64 { - return int64(c.GetFloat64(pattern)) -} +// 返回指定json中的float64->uint +func (c *Config) GetUint(pattern string, files...string) uint { + if j := c.getJson(files); j != nil { + return j.GetUint(pattern) + } + return 0 +} \ No newline at end of file diff --git a/geg/database/mysql/mysql.go b/geg/database/mysql/mysql.go index cdd7f15c1..172e57292 100644 --- a/geg/database/mysql/mysql.go +++ b/geg/database/mysql/mysql.go @@ -17,7 +17,7 @@ func init () { Port : "3306", User : "root", Pass : "123456", - Name : "test2", + Name : "test", Type : "mysql", Role : "master", Charset : "utf8", @@ -416,7 +416,7 @@ func main() { //create() //create() //insert() - //query() + query() //replace() //save() //batchInsert() diff --git a/geg/other/test.go b/geg/other/test.go index 154f87dfc..c614d0644 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,8 +2,56 @@ package main import ( "fmt" + "gitee.com/johng/gf/g/encoding/gxml" + "gitee.com/johng/gf/g/os/gfile" ) func main() { - fmt.Printf("%b\n", 123) + //json := gfile.GetBinContents("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/config.json") + //y, err := yaml.JSONToYAML(json) + //fmt.Println(err) + //fmt.Println(string(y)) + // + //j, err := yaml.YAMLToJSON(y) + //fmt.Println(err) + //fmt.Println(string(j)) + + x := ` + + + + Comments for 碎言碎语 + + http://johng.cn + + Fri, 05 Jan 2018 02:56:11 +0000 + hourly + 1 + https://wordpress.org/?v=4.7.3 + + Comment on Go性能优化:string与[ ]byte转换 by John + http://johng.cn/go-optimize-string-bytes/#comment-114 + + Fri, 05 Jan 2018 02:56:11 +0000 + http://johng.cn/?p=3435#comment-114 + + 这篇文章我转自雨痕,由于string和[]byte之间的转换比较常用,所以这篇文章的性能对比才比较惊人。其他基本类型与[]byte这件的转换性能差别不大,struct与[]byte的转换性能差别主要在数据结构设计上,比如socket通信的话,基本都是自己通过二进制转换来组织需要的数据结构。总得来说,在go开发的时候尽量多用二进制参数([]byte)是好的。

+]]>
+
+ + + Comment on 层次不同的人,是很难沟通的 by buhuipao + http://johng.cn/hard-for-communitication-between-different-levels/#comment-105 + + Tue, 19 Sep 2017 09:10:08 +0000 + http://johng.cn/?p=2854#comment-105 + + 博主说得很对,认知很重要。

+]]>
+
+
+
` + + j, _ := gxml.ToJson([]byte(x)) + fmt.Println(string(j)) } \ No newline at end of file