zoukankan      html  css  js  c++  java
  • go 字符串转换

    Go语言json编码驼峰转下划线、下划线转驼峰

     

    一、需求

    golang默认的结构体json转码出来,都是根据字段名生成的大写驼峰格式,但是一般我们最常用的json格式是小写驼峰或者小写下划线,因此,我们非常需要一个统一的方法去转换,而不想挨个写json标签,例如

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    func main() {
    	type Person struct {
    		HelloWold       string
    		LightWeightBaby string
    	}
    	var a = Person{HelloWold: "chenqionghe", LightWeightBaby: "muscle"}
    	res, _ := json.Marshal(a)
    	fmt.Printf("%s", res)
    }
    

    运行结果

    {"HelloWold":"chenqionghe","LightWeightBaby":"muscle"}
    

    输出来的json结构是大写驼峰的,肯定非常别扭,当然 ,我们通过设定json标签来设定输出的json字段名,例如

    type Person struct {
    	HelloWold       string `json:"hello_wold"`
    	LightWeightBaby string `json:"light_weight_baby"`
    }
    

    但是如果字段特别多,需要挨个设置也太麻烦了。

    二、实现

    Golang 的标准 Json 在处理各种数据类型是都是调用其类型接口UnmarshalJSON解码和MarshalJSON编码进行转换的,所以我们可以封装一个统一转换下划线的json结构体或统一转换驼峰的json结构体,并实现MarshalJSON方法,就可以达到目的。
    实现如下

    package jsonconv
    
    import (
    	"bytes"
    	"encoding/json"
    	"log"
    	"regexp"
    	"strconv"
    	"strings"
    	"unicode"
    )
    
    /*************************************** 下划线json ***************************************/
    type JsonSnakeCase struct {
    	Value interface{}
    }
    
    func (c JsonSnakeCase) MarshalJSON() ([]byte, error) {
    	// Regexp definitions
    	var keyMatchRegex = regexp.MustCompile(`"(w+)":`)
    	var wordBarrierRegex = regexp.MustCompile(`(w)([A-Z])`)
    	marshalled, err := json.Marshal(c.Value)
    	converted := keyMatchRegex.ReplaceAllFunc(
    		marshalled,
    		func(match []byte) []byte {
    			return bytes.ToLower(wordBarrierRegex.ReplaceAll(
    				match,
    				[]byte(`${1}_${2}`),
    			))
    		},
    	)
    	return converted, err
    }
    
    /*************************************** 驼峰json ***************************************/
    type JsonCamelCase struct {
    	Value interface{}
    }
    
    func (c JsonCamelCase) MarshalJSON() ([]byte, error) {
    	var keyMatchRegex = regexp.MustCompile(`"(w+)":`)
    	marshalled, err := json.Marshal(c.Value)
    	converted := keyMatchRegex.ReplaceAllFunc(
    		marshalled,
    		func(match []byte) []byte {
    			matchStr := string(match)
    			key := matchStr[1 : len(matchStr)-2]
    			resKey := Lcfirst(Case2Camel(key))
    			return []byte(`"` + resKey + `":`)
    		},
    	)
    	return converted, err
    }
    
    /*************************************** 其他方法 ***************************************/
    // 驼峰式写法转为下划线写法
    func Camel2Case(name string) string {
    	buffer := NewBuffer()
    	for i, r := range name {
    		if unicode.IsUpper(r) {
    			if i != 0 {
    				buffer.Append('_')
    			}
    			buffer.Append(unicode.ToLower(r))
    		} else {
    			buffer.Append(r)
    		}
    	}
    	return buffer.String()
    }
    
    // 下划线写法转为驼峰写法
    func Case2Camel(name string) string {
    	name = strings.Replace(name, "_", " ", -1)
    	name = strings.Title(name)
    	return strings.Replace(name, " ", "", -1)
    }
    
    // 首字母大写
    func Ucfirst(str string) string {
    	for i, v := range str {
    		return string(unicode.ToUpper(v)) + str[i+1:]
    	}
    	return ""
    }
    
    // 首字母小写
    func Lcfirst(str string) string {
    	for i, v := range str {
    		return string(unicode.ToLower(v)) + str[i+1:]
    	}
    	return ""
    }
    
    // 内嵌bytes.Buffer,支持连写
    type Buffer struct {
    	*bytes.Buffer
    }
    
    func NewBuffer() *Buffer {
    	return &Buffer{Buffer: new(bytes.Buffer)}
    }
    
    func (b *Buffer) Append(i interface{}) *Buffer {
    	switch val := i.(type) {
    	case int:
    		b.append(strconv.Itoa(val))
    	case int64:
    		b.append(strconv.FormatInt(val, 10))
    	case uint:
    		b.append(strconv.FormatUint(uint64(val), 10))
    	case uint64:
    		b.append(strconv.FormatUint(val, 10))
    	case string:
    		b.append(val)
    	case []byte:
    		b.Write(val)
    	case rune:
    		b.WriteRune(val)
    	}
    	return b
    }
    
    func (b *Buffer) append(s string) *Buffer {
    	defer func() {
    		if err := recover(); err != nil {
    			log.Println("*****内存不够了!******")
    		}
    	}()
    	b.WriteString(s)
    	return b
    }
    

    三、使用

    JsonSnakeCase统一转下划线json

    使用jsonconv.JsonSnakeCase包裹一下要输出json的对象即可

    func main() {
    	type Person struct {
    		HelloWold       string
    		LightWeightBaby string
    	}
    	var a = Person{HelloWold: "chenqionghe", LightWeightBaby: "muscle"}
    	res, _ := json.Marshal(jsonconv.JsonSnakeCase{a})
    	fmt.Printf("%s", res)
    }
    

    输出如下

    {"hello_wold":"chenqionghe","light_weight_baby":"muscle"}
    

    JsonCamelCase统一转驼峰json

    已经指定了下划线标签的结构体,我们也可以统一转为驼峰的json

    func main() {
    	type Person struct {
    		HelloWold       string `json:"hello_wold"`
    		LightWeightBaby string `json:"light_weight_baby"`
    	}
    	var a = Person{HelloWold: "chenqionghe", LightWeightBaby: "muscle"}
    	res, _ := json.Marshal(jsonconv.JsonCamelCase{a})
    	fmt.Printf("%s", res)
    }
    

    输出如下

    {"helloWold":"chenqionghe","lightWeightBaby":"muscle"}
    

    非常方便的解决了json统一转码格式的需求

  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/whm-blog/p/13590813.html
Copyright © 2011-2022 走看看