Build and unpack pointer values
Signed-off-by: Jingwen Peng <pengsrc@yunify.com>
This commit is contained in:
parent
a675c48f6c
commit
ee0075ad77
|
@ -92,11 +92,14 @@ func (b *Builder) parseRequestProperties() error {
|
||||||
fields := reflect.ValueOf(b.operation.Properties).Elem()
|
fields := reflect.ValueOf(b.operation.Properties).Elem()
|
||||||
for i := 0; i < fields.NumField(); i++ {
|
for i := 0; i < fields.NumField(); i++ {
|
||||||
switch value := fields.Field(i).Interface().(type) {
|
switch value := fields.Field(i).Interface().(type) {
|
||||||
case string:
|
case *string:
|
||||||
propertiesMap[fields.Type().Field(i).Tag.Get("name")] = value
|
if value != nil {
|
||||||
case int:
|
propertiesMap[fields.Type().Field(i).Tag.Get("name")] = *value
|
||||||
numberString := strconv.Itoa(int(value))
|
}
|
||||||
propertiesMap[fields.Type().Field(i).Tag.Get("name")] = numberString
|
case *int:
|
||||||
|
if value != nil {
|
||||||
|
propertiesMap[fields.Type().Field(i).Tag.Get("name")] = strconv.Itoa(int(*value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,57 +131,47 @@ func (b *Builder) parseRequestParams() error {
|
||||||
tagDefault := b.input.Elem().Type().Field(i).Tag.Get("default")
|
tagDefault := b.input.Elem().Type().Field(i).Tag.Get("default")
|
||||||
if tagName != "" && tagLocation != "" && requestParams != nil {
|
if tagName != "" && tagLocation != "" && requestParams != nil {
|
||||||
switch value := b.input.Elem().Field(i).Interface().(type) {
|
switch value := b.input.Elem().Field(i).Interface().(type) {
|
||||||
case string:
|
case *string:
|
||||||
if value != "" {
|
if tagDefault != "" {
|
||||||
requestParams[tagName] = value
|
requestParams[tagName] = tagDefault
|
||||||
}
|
}
|
||||||
case int:
|
if value != nil {
|
||||||
numberString := strconv.Itoa(int(value))
|
requestParams[tagName] = *value
|
||||||
if numberString == "0" {
|
|
||||||
numberString = ""
|
|
||||||
if tagDefault != "" {
|
|
||||||
numberString = tagDefault
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if numberString != "" {
|
case *int:
|
||||||
requestParams[tagName] = numberString
|
if tagDefault != "" {
|
||||||
|
requestParams[tagName] = tagDefault
|
||||||
}
|
}
|
||||||
case bool:
|
if value != nil {
|
||||||
case time.Time:
|
requestParams[tagName] = strconv.Itoa(int(*value))
|
||||||
zero := time.Time{}
|
}
|
||||||
if value != zero {
|
case *bool:
|
||||||
var timeString string
|
case *time.Time:
|
||||||
|
if tagDefault != "" {
|
||||||
|
requestParams[tagName] = tagDefault
|
||||||
|
}
|
||||||
|
if value != nil {
|
||||||
format := b.input.Elem().Type().Field(i).Tag.Get("format")
|
format := b.input.Elem().Type().Field(i).Tag.Get("format")
|
||||||
timeString = utils.TimeToString(value, format)
|
requestParams[tagName] = utils.TimeToString(*value, format)
|
||||||
if timeString != "" {
|
}
|
||||||
requestParams[tagName] = timeString
|
case []*string:
|
||||||
|
for index, item := range value {
|
||||||
|
key := tagName + "." + strconv.Itoa(index+1)
|
||||||
|
if tagDefault != "" {
|
||||||
|
requestParams[tagName] = tagDefault
|
||||||
|
}
|
||||||
|
if item != nil {
|
||||||
|
requestParams[key] = *item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case []string:
|
case []*int:
|
||||||
if len(value) > 0 {
|
for index, item := range value {
|
||||||
for index, item := range value {
|
key := tagName + "." + strconv.Itoa(index+1)
|
||||||
key := tagName + "." + strconv.Itoa(index+1)
|
if tagDefault != "" {
|
||||||
requestParams[key] = item
|
requestParams[tagName] = tagDefault
|
||||||
}
|
}
|
||||||
}
|
if item != nil {
|
||||||
case []int:
|
requestParams[key] = strconv.Itoa(int(*item))
|
||||||
if len(value) > 0 {
|
|
||||||
numbersString := []string{}
|
|
||||||
for _, number := range value {
|
|
||||||
numberString := strconv.Itoa(int(number))
|
|
||||||
if numberString == "0" {
|
|
||||||
numberString = ""
|
|
||||||
if tagDefault != "" {
|
|
||||||
numberString = tagDefault
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if numberString != "" {
|
|
||||||
numbersString = append(numbersString, numberString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, item := range numbersString {
|
|
||||||
requestParams[tagName+"."+strconv.Itoa(index+1)] = item
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -197,20 +190,13 @@ func (b *Builder) parseRequestParams() error {
|
||||||
tagKey := tagName + "." + strconv.Itoa(i+1) + "." + fieldTagName
|
tagKey := tagName + "." + strconv.Itoa(i+1) + "." + fieldTagName
|
||||||
|
|
||||||
switch fieldValue := item.Field(j).Interface().(type) {
|
switch fieldValue := item.Field(j).Interface().(type) {
|
||||||
case int:
|
case *int:
|
||||||
numberString := strconv.Itoa(int(fieldValue))
|
if fieldValue != nil {
|
||||||
if numberString == "0" {
|
requestParams[tagKey] = strconv.Itoa(int(*fieldValue))
|
||||||
numberString = ""
|
|
||||||
if tagDefault != "" {
|
|
||||||
numberString = tagDefault
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if numberString != "" {
|
case *string:
|
||||||
requestParams[tagKey] = numberString
|
if fieldValue != nil {
|
||||||
}
|
requestParams[tagKey] = *fieldValue
|
||||||
case string:
|
|
||||||
if fieldValue != "" {
|
|
||||||
requestParams[tagKey] = fieldValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,25 +27,42 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstanceServiceProperties struct {
|
type InstanceServiceProperties struct {
|
||||||
Zone string `json:"zone" name:"zone"` // Required
|
Zone *string `json:"zone" name:"zone"` // Required
|
||||||
}
|
}
|
||||||
|
|
||||||
type DescribeInstancesInput struct {
|
type DescribeInstancesInput struct {
|
||||||
ImageID []string `json:"image_id" name:"image_id" location:"params"`
|
ImageID []*string `json:"image_id" name:"image_id" location:"params"`
|
||||||
InstanceClass int `json:"instance_class" name:"instance_class" location:"params" default:"0"` // Available values: 0, 1
|
InstanceClass *int `json:"instance_class" name:"instance_class" location:"params" default:"0"` // Available values: 0, 1
|
||||||
InstanceType []string `json:"instance_type" name:"instance_type" location:"params"`
|
InstanceType []*string `json:"instance_type" name:"instance_type" location:"params"`
|
||||||
Instances []string `json:"instances" name:"instances" location:"params"`
|
Instances []*string `json:"instances" name:"instances" location:"params"`
|
||||||
Limit int `json:"limit" name:"limit" omitEmpty:"true" location:"params"`
|
Limit *int `json:"limit" name:"limit" location:"params"`
|
||||||
Offset int `json:"offset" name:"offset" location:"params"`
|
Offset *int `json:"offset" name:"offset" location:"params"`
|
||||||
SearchWord string `json:"search_word" name:"search_word" location:"params"`
|
SearchWord *string `json:"search_word" name:"search_word" location:"params"`
|
||||||
Status []string `json:"status" name:"status" location:"params"` // Available values: pending, running, stopped, suspended, terminated, ceased
|
Status []*string `json:"status" name:"status" location:"params"` // Available values: pending, running, stopped, suspended, terminated, ceased
|
||||||
Tags []string `json:"tags" name:"tags" location:"params"`
|
Tags []*string `json:"tags" name:"tags" location:"params"`
|
||||||
Verbose int `json:"verbose" name:"verbose" location:"params"` // Available values: 0, 1
|
Verbose *int `json:"verbose" name:"verbose" location:"params"` // Available values: 0, 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *DescribeInstancesInput) Validate() error {
|
func (i *DescribeInstancesInput) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func String(v string) *string {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringSlice(src []string) []*string {
|
||||||
|
dst := make([]*string, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int(v int) *int {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilder(t *testing.T) {
|
func TestBuilder(t *testing.T) {
|
||||||
|
|
||||||
conf, err := config.NewDefault()
|
conf, err := config.NewDefault()
|
||||||
|
@ -56,7 +73,7 @@ func TestBuilder(t *testing.T) {
|
||||||
operation := &data.Operation{
|
operation := &data.Operation{
|
||||||
Config: conf,
|
Config: conf,
|
||||||
Properties: &InstanceServiceProperties{
|
Properties: &InstanceServiceProperties{
|
||||||
Zone: "beta",
|
Zone: String("beta"),
|
||||||
},
|
},
|
||||||
APIName: "DescribeInstances",
|
APIName: "DescribeInstances",
|
||||||
ServiceName: "Instance",
|
ServiceName: "Instance",
|
||||||
|
@ -67,16 +84,14 @@ func TestBuilder(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
inputValue := reflect.ValueOf(&DescribeInstancesInput{
|
inputValue := reflect.ValueOf(&DescribeInstancesInput{
|
||||||
ImageID: []string{"img-xxxxxxxx", "img-zzzzzzzz"},
|
ImageID: StringSlice([]string{"img-xxxxxxxx", "img-zzzzzzzz"}),
|
||||||
InstanceClass: 0,
|
InstanceClass: Int(0),
|
||||||
InstanceType: []string{"type1", "type2"},
|
InstanceType: StringSlice([]string{"type1", "type2"}),
|
||||||
Instances: []string{"i-xxxxxxxx", "i-zzzzzzzz"},
|
Instances: StringSlice([]string{"i-xxxxxxxx", "i-zzzzzzzz"}),
|
||||||
Limit: 0,
|
SearchWord: String("search_word"),
|
||||||
Offset: 0,
|
Status: StringSlice([]string{"running"}),
|
||||||
SearchWord: "search_word",
|
Tags: StringSlice([]string{"tag1", "tag2"}),
|
||||||
Status: []string{"running"},
|
Verbose: Int(1),
|
||||||
Tags: []string{"tag1", "tag2"},
|
|
||||||
Verbose: 1,
|
|
||||||
})
|
})
|
||||||
httpRequest, err := builder.BuildHTTPRequest(operation, &inputValue)
|
httpRequest, err := builder.BuildHTTPRequest(operation, &inputValue)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -122,13 +122,13 @@ func (u *Unpacker) parseError() error {
|
||||||
retCodeValue := u.output.Elem().FieldByName("RetCode")
|
retCodeValue := u.output.Elem().FieldByName("RetCode")
|
||||||
messageValue := u.output.Elem().FieldByName("Message")
|
messageValue := u.output.Elem().FieldByName("Message")
|
||||||
|
|
||||||
if retCodeValue.IsValid() && retCodeValue.Type().String() == "int" &&
|
if retCodeValue.IsValid() && retCodeValue.Type().String() == "*int" &&
|
||||||
messageValue.IsValid() && messageValue.Type().String() == "string" &&
|
messageValue.IsValid() && messageValue.Type().String() == "*string" &&
|
||||||
retCodeValue.Int() != 0 {
|
retCodeValue.Elem().Int() != 0 {
|
||||||
|
|
||||||
return &errors.QingCloudError{
|
return &errors.QingCloudError{
|
||||||
RetCode: int(retCodeValue.Int()),
|
RetCode: int(retCodeValue.Elem().Int()),
|
||||||
Message: messageValue.String(),
|
Message: messageValue.Elem().String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,33 +30,54 @@ import (
|
||||||
"github.com/yunify/qingcloud-sdk-go/request/errors"
|
"github.com/yunify/qingcloud-sdk-go/request/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func StringValue(v *string) string {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func IntValue(v *int) int {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimeValue(v *time.Time) time.Time {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnpackerUnpackHTTPRequest(t *testing.T) {
|
func TestUnpackerUnpackHTTPRequest(t *testing.T) {
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
Device string `json:"device" name:"device"`
|
Device *string `json:"device" name:"device"`
|
||||||
InstanceID string `json:"instance_id" name:"instance_id"`
|
InstanceID *string `json:"instance_id" name:"instance_id"`
|
||||||
InstanceName string `json:"instance_name" name:"instance_name"`
|
InstanceName *string `json:"instance_name" name:"instance_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Volume struct {
|
type Volume struct {
|
||||||
CreateTime time.Time `json:"create_time" name:"create_time" format:"ISO 8601"`
|
CreateTime *time.Time `json:"create_time" name:"create_time" format:"ISO 8601"`
|
||||||
Description string `json:"description" name:"description"`
|
Description *string `json:"description" name:"description"`
|
||||||
Instance *Instance `json:"instance" name:"instance"`
|
Instance *Instance `json:"instance" name:"instance"`
|
||||||
Size int `json:"size" name:"size"`
|
Size *int `json:"size" name:"size"`
|
||||||
Status string `json:"status" name:"status"`
|
Status *string `json:"status" name:"status"`
|
||||||
StatusTime time.Time `json:"status_time" name:"status_time" format:"ISO 8601"`
|
StatusTime *time.Time `json:"status_time" name:"status_time" format:"ISO 8601"`
|
||||||
SubCode int `json:"sub_code" name:"sub_code"`
|
SubCode *int `json:"sub_code" name:"sub_code"`
|
||||||
TransitionStatus string `json:"transition_status" name:"transition_status"`
|
TransitionStatus *string `json:"transition_status" name:"transition_status"`
|
||||||
VolumeID string `json:"volume_id" name:"volume_id"`
|
VolumeID *string `json:"volume_id" name:"volume_id"`
|
||||||
VolumeName string `json:"volume_name" name:"volume_name"`
|
VolumeName *string `json:"volume_name" name:"volume_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DescribeVolumesOutput struct {
|
type DescribeVolumesOutput struct {
|
||||||
StatusCode int `location:"statusCode"`
|
StatusCode int `location:"statusCode"`
|
||||||
Error *errors.QingCloudError
|
Error *errors.QingCloudError
|
||||||
|
|
||||||
Action string `json:"action" name:"action"`
|
Action *string `json:"action" name:"action"`
|
||||||
RetCode int `json:"ret_code" name:"ret_code"`
|
RetCode *int `json:"ret_code" name:"ret_code"`
|
||||||
TotalCount int `json:"total_count" name:"total_count"`
|
TotalCount *int `json:"total_count" name:"total_count"`
|
||||||
VolumeSet []*Volume `json:"volume_set" name:"volume_set"`
|
VolumeSet []*Volume `json:"volume_set" name:"volume_set"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,18 +115,18 @@ func TestUnpackerUnpackHTTPRequest(t *testing.T) {
|
||||||
unpacker := Unpacker{}
|
unpacker := Unpacker{}
|
||||||
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
err := unpacker.UnpackHTTPRequest(&data.Operation{}, httpResponse, &outputValue)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "i-xxxxxxxx", output.VolumeSet[0].Instance.InstanceID)
|
assert.Equal(t, "i-xxxxxxxx", StringValue(output.VolumeSet[0].Instance.InstanceID))
|
||||||
assert.Equal(t, "vol-xxxxxxxx", output.VolumeSet[0].VolumeID)
|
assert.Equal(t, "vol-xxxxxxxx", StringValue(output.VolumeSet[0].VolumeID))
|
||||||
assert.Equal(t, "vol name", output.VolumeSet[0].VolumeName)
|
assert.Equal(t, "vol name", StringValue(output.VolumeSet[0].VolumeName))
|
||||||
assert.Equal(t, 1024, output.TotalCount)
|
assert.Equal(t, 1024, IntValue(output.TotalCount))
|
||||||
statusTime := time.Date(2013, 8, 30, 5, 13, 32, 0, time.UTC)
|
statusTime := time.Date(2013, 8, 30, 5, 13, 32, 0, time.UTC)
|
||||||
assert.Equal(t, statusTime, output.VolumeSet[0].StatusTime)
|
assert.Equal(t, statusTime, TimeValue(output.VolumeSet[0].StatusTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnpacker_UnpackHTTPRequestWithError(t *testing.T) {
|
func TestUnpacker_UnpackHTTPRequestWithError(t *testing.T) {
|
||||||
type DescribeInstanceTypesOutput struct {
|
type DescribeInstanceTypesOutput struct {
|
||||||
RetCode int `json:"ret_code" name:"ret_code"`
|
RetCode *int `json:"ret_code" name:"ret_code"`
|
||||||
Message string `json:"message" name:"message"`
|
Message *string `json:"message" name:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
httpResponse := &http.Response{Header: http.Header{}}
|
httpResponse := &http.Response{Header: http.Header{}}
|
||||||
|
|
Loading…
Reference in New Issue