1 Star 0 Fork 0

爱薄荷的小虾米/aws-sdk-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
build.go 4.24 KB
一键复制 编辑 原始数据 按行查看 历史
lijunwei123 提交于 2015-06-08 15:20 . first
// Package jsonutil provides JSON serialisation of AWS requests and responses.
package jsonutil
import (
"bytes"
"encoding/base64"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
)
// BuildJSON builds a JSON string for a given object v.
func BuildJSON(v interface{}) ([]byte, error) {
var buf bytes.Buffer
err := buildAny(reflect.ValueOf(v), &buf, "")
return buf.Bytes(), err
}
func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
value = reflect.Indirect(value)
if !value.IsValid() {
return nil
}
vtype := value.Type()
t := tag.Get("type")
if t == "" {
switch vtype.Kind() {
case reflect.Struct:
// also it can't be a time object
if _, ok := value.Interface().(time.Time); !ok {
t = "structure"
}
case reflect.Slice:
// also it can't be a byte slice
if _, ok := value.Interface().([]byte); !ok {
t = "list"
}
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
if field, ok := vtype.FieldByName("SDKShapeTraits"); ok {
tag = field.Tag
}
return buildStruct(value, buf, tag)
case "list":
return buildList(value, buf, tag)
case "map":
return buildMap(value, buf, tag)
default:
return buildScalar(value, buf, tag)
}
}
func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
if !value.IsValid() {
return nil
}
buf.WriteString("{")
t, fields := value.Type(), []*reflect.StructField{}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
member := value.FieldByName(field.Name)
if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() {
continue // ignore unset fields
}
if c := field.Name[0:1]; strings.ToLower(c) == c {
continue // ignore unexported fields
}
if field.Tag.Get("location") != "" {
continue // ignore non-body elements
}
fields = append(fields, &field)
}
for i, field := range fields {
member := value.FieldByName(field.Name)
// figure out what this field is called
name := field.Name
if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
buf.WriteString(fmt.Sprintf("%q:", name))
err := buildAny(member, buf, field.Tag)
if err != nil {
return err
}
if i < len(fields)-1 {
buf.WriteString(",")
}
}
buf.WriteString("}")
return nil
}
func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
buf.WriteString("[")
for i := 0; i < value.Len(); i++ {
buildAny(value.Index(i), buf, "")
if i < value.Len()-1 {
buf.WriteString(",")
}
}
buf.WriteString("]")
return nil
}
func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
buf.WriteString("{")
keys := make([]string, value.Len())
for i, n := range value.MapKeys() {
keys[i] = n.String()
}
sort.Strings(keys)
for i, k := range keys {
buf.WriteString(fmt.Sprintf("%q:", k))
buildAny(value.MapIndex(reflect.ValueOf(k)), buf, "")
if i < len(keys)-1 {
buf.WriteString(",")
}
}
buf.WriteString("}")
return nil
}
func buildScalar(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
switch converted := value.Interface().(type) {
case string:
writeString(converted, buf)
case []byte:
if !value.IsNil() {
buf.WriteString(fmt.Sprintf("%q", base64.StdEncoding.EncodeToString(converted)))
}
case bool:
buf.WriteString(strconv.FormatBool(converted))
case int64:
buf.WriteString(strconv.FormatInt(converted, 10))
case float64:
buf.WriteString(strconv.FormatFloat(converted, 'f', -1, 64))
case time.Time:
buf.WriteString(strconv.FormatInt(converted.UTC().Unix(), 10))
default:
return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type())
}
return nil
}
func writeString(s string, buf *bytes.Buffer) {
buf.WriteByte('"')
for _, r := range s {
if r == '"' {
buf.WriteString(`\"`)
} else if r == '\\' {
buf.WriteString(`\\`)
} else if r == '\b' {
buf.WriteString(`\b`)
} else if r == '\f' {
buf.WriteString(`\f`)
} else if r == '\r' {
buf.WriteString(`\r`)
} else if r == '\t' {
buf.WriteString(`\t`)
} else if r == '\n' {
buf.WriteString(`\n`)
} else if r < 32 {
fmt.Fprintf(buf, "\\u%0.4x", r)
} else {
buf.WriteRune(r)
}
}
buf.WriteByte('"')
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/cqclife/aws-sdk-go.git
git@gitee.com:cqclife/aws-sdk-go.git
cqclife
aws-sdk-go
aws-sdk-go
v1.0.10

搜索帮助