golang json

基本用法

Escape开关

uint64位精度缺失

// JSONUnMarshal 设置UseNumber,防止uint64位精度缺失
func JSONUnMarshal(jsonStream []byte, ret interface{}) error {
    decoder := json.NewDecoder(strings.NewReader(string(jsonStream)))
    decoder.UseNumber()
    if err := decoder.Decode(&ret); err != nil {
        fmt.Println("error:", err)
        return err
    }
    return nil
}

案例记录

GoLang结构体转json,避免对[]byte进行base64

背景

golang中用protobuf 2处理,会生成如下格式结构体 :

type KbVideoInput struct {
	KbArticleId         []byte `protobuf:"bytes,1,opt,name=kb_article_id" json:"kb_article_id,omitempty"`
	Title               []byte `protobuf:"bytes,2,opt,name=title" json:"title,omitempty"`
	Time                *uint32  `protobuf:"varint,5,opt,name=time" json:"time,omitempty"`
	NewIndexScore       *float64        `protobuf:"fixed64,92,opt,name=new_index_score" json:"new_index_score,omitempty"`
	}

处理方案

为解决上述问题,通过两个函数:

代码记录:

  1. 根据json tag转换struct到map中
// 只解析struct第一层结构
func StuctToJsonMap(structData interface{}) *map[string]interface{} {
    ret := make(map[string]interface{})
    TypeData := reflect.TypeOf(structData).Elem()
    ValueData := reflect.ValueOf(structData).Elem()
    for i := 0; i < TypeData.NumField(); i++ {
        fieldKey := TypeData.Field(i)
        fieldVal := ValueData.Field(i)
        tagKey, tagOp := parseTag(fieldKey.Tag.Get("json"))
        if tagKey == "-" {
            continue
        }
        //fmt.Printf("tagKey: %s, tag op: %s\n", tagKey, tagOp)
        //fmt.Printf("fieldVal: %s, fieldVal.IsValid: %v\n", fieldVal, fieldVal.IsNil())
        if !fieldVal.IsNil() {
            ret[tagKey] = fieldVal.Interface()
        } else {
            if tagOp != "omitempty" {
                ret[tagKey] = fieldVal.Interface()
            }
        }
    }
    return &ret
}

// tagOptions is the string following a comma in a struct field's "json"
// tag, or the empty string. It does not include the leading comma.
type tagOptions string

// parseTag splits a struct field's json tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
    if idx := strings.Index(tag, ","); idx != -1 {
        return tag[:idx], tagOptions(tag[idx+1:])
    }
    return tag, tagOptions("")
}
  1. map中的byte转string处理,防止json出现base64
// map中的byte转string处理,防止json出现base64
// map中的指针格式转成非指针
func FormatValue(dataMap *map[string]interface{}) {
    for k, v := range *dataMap {
        //fmt.Printf("key: %s, val: %+v, type: %s\n", k, v, reflect.TypeOf(v))
        switch v.(type) {
        case []byte:
            (*dataMap)[k] = string(v.([]byte))
        case json.RawMessage:
            (*dataMap)[k] = string(v.(json.RawMessage))
        case *uint32:
            (*dataMap)[k] = *v.(*uint32)
        case *int64:
            (*dataMap)[k] = *v.(*int64)
        case *int32:
            (*dataMap)[k] = *v.(*int32)
        case *string:
            (*dataMap)[k] = *v.(*string)
        default:
            (*dataMap)[k] = v
        }
    }
}
  1. 使用
    reqMap := es_helper.StuctToJsonMap(&reqStruct)  // reqStruct为golang数据结构
    FormatValue(reqMap)
    nLog.Info("req data: %s", reqData)
    reqJson, err := JsonMarshal(&reqMap)
Table of Contents