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