go编解码json和http请求
1.json概述
json是日常工作中http请求的最重要的数据格式。对比日常使用python中的json,获得http请求后json.loads和json.dumps函数,go中显的非常麻烦,这里结合json和http请求的总结下,便于积累和学习。这里给出一个json的类型,包括了数组对象等各种格式,以请求云计算的伸缩组的接口为例
{"ResponseMetadata": {"RequestId": "202504291928461ASBCDEDGSGGSBCD8A4862","Action": "DescribeScalingGroups","Version": "2020-01-01","Service": "auto_scaling","Region": "cn-beijing"},"Result": {"ScalingGroups": [{"ScalingGroupId": "scg-ydukizremqd0qsyqoc0k","ScalingGroupName": "test_create_recurrence_policy_without_end_time","LifecycleState": "Active","HealthCheckType": "ECS","VpcId": "vpc-2ff4fh7wic2dc59gp67u70mpn","SubnetIds": ["subnet-imc2pmpasbuo8gbssz4tv3cw"],"DefaultCooldown": 5,"ActiveScalingConfigurationId": "scc-ydukizstwjiq4jg1ggfy","DesireInstanceNumber": 2,"MinInstanceNumber": 0,"MaxInstanceNumber": 10,"InstanceTerminatePolicy": "OldestScalingConfigurationWithNewestInstance","ServerGroupAttributes": [],"CreatedAt": "2025-04-27T07:53:37Z","UpdatedAt": "2025-04-27T16:00:00Z","TotalInstanceCount": 2,"DBInstanceIds": [],"MultiAZPolicy": "BALANCE","LaunchTemplateId": "","LaunchTemplateVersion": "","DesireCapacityType": "units","MinSize": 0,"MaxSize": 0,"DesireCapacity": -1,"TotalCapacity": 0,"LaunchTemplateOverrides": [],"ScalingMode": "release","StoppedInstanceCount": 0,"StoppedCapacity": 0,"ProjectName": "default","Tags": [{"Key": "k1","Value": "v1"}],"LoadBalancerHealthCheckGracePeriod": 300,"InstancesDistribution": {"OnDemandBaseCapacity": 0,"OnDemandPercentageAboveBaseCapacity": 0,"CompensateWithOnDemand": false,"SpotInstanceRemedy": false},"SuspendedProcesses": []}],"NextToken": ""}
}
这个是调用DescribeScalingGroups接口查询指定ScalingGroupId参数的响应结果。这里先声明两个概念
序列化和反序列化
- 序列化
就是将对象转化成二进制序列的过程。我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
- 反序列化
就是讲二进制序列转化成对象的过程。 把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
实际工作中,解析返回到JSON有三种方式:
- 解析到结构体,使用map[string]interfance{}先接过来
- 解析到interface,使用map[string]interface{}先接过来
- 第三方包SimpleJSON,单纯的数据解析
上述的JSON返回数据,因为查询了指定的ScalingGroupId,希望在ScalingGroups结果判断下伸缩组的状态LifecycleState是否是Active。
查询接口DescribeScalingGroups返回的结果*output如下所示
map[ResponseMetadata:map[Action:DescribeScalingGroups Region:cn-beijing RequestId:20250429200529F297B9ADFGHJKDS96346 Service:auto_scaling Version:2020-01-01] Result:map[PageNumber:1 PageSize:10 ScalingGroups:[map[ActiveScalingConfigurationId:scc-ydukizstwjiq4jg1ggfy CreatedAt:2025-04-27T07:53:37Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:2 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithNewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:10 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:BALANCE ProjectName:default ScalingGroupId:scg-ydukizremqd0qsyqoc0k ScalingGroupName:test_create_recurrence_policy_without_end_time ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-imc2pmpasbuo8gbssz4tv3cw] SuspendedProcesses:[] Tags:[map[Key:k1 Value:v1]] TotalCapacity:0 TotalInstanceCount:2 UpdatedAt:2025-04-27T16:00:00Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn] map[ActiveScalingConfigurationId:scc-ydufdt2e8dd0qtlr2121 CreatedAt:2025-04-25T08:25:00Z DBInstanceIds:[] DefaultCooldown:300 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:-1 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithOldestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:1 MaxSize:0 MinInstanceNumber:1 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-ydufdqucghiq4k6pncgf ScalingGroupName:tjhs ScalingMode:recycle ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-imdl1ew9i03k8gbssyvxv53q] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:1 UpdatedAt:2025-04-25T08:25:59Z VpcId:vpc-imbcb3doyr5s8gbssxzkz7zt] map[ActiveScalingConfigurationId: CreatedAt:2025-04-25T08:10:17Z DBInstanceIds:[] DefaultCooldown:300 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:1 HealthCheckType:ECS InstanceTerminatePolicy:NewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:InActive LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:100 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-ydufcse0jaiq4k3hz5nw ScalingGroupName:wxy-recycle-混合计费缩容4 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-12arsfcvsqvi817q7y2rplfif] SuspendedProcesses:[] Tags:[map[Key:volc:vke:Id Value:1]] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-25T08:10:17Z VpcId:vpc-imbcb3doyr5s8gbssxzkz7zt] map[ActiveScalingConfigurationId: CreatedAt:2025-04-25T06:08:23Z DBInstanceIds:[] DefaultCooldown:300 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:1 HealthCheckType:ECS InstanceTerminatePolicy:NewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:InActive LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:100 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-yduf4uysvnd0qs4juwot ScalingGroupName:wxy-recycle-混合计费缩容2 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-12arsfcvsqvi817q7y2rplfif] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-25T06:08:23Z VpcId:vpc-imbcb3doyr5s8gbssxzkz7zt] map[ActiveScalingConfigurationId:scc-yduc64xga6d0qsvqjf7d CreatedAt:2025-04-24T02:46:41Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:12 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithOldestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:100 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-yduc63lnuqiq4k6il4vh ScalingGroupName:wxy-metric-test ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-imdl1ew9i03k8gbssyvxv53q] SuspendedProcesses:[] Tags:[map[Key:sys Value:]] TotalCapacity:0 TotalInstanceCount:11 UpdatedAt:2025-04-28T16:00:00Z VpcId:vpc-imbcb3doyr5s8gbssxzkz7zt] map[ActiveScalingConfigurationId:scc-ydu5dwgxt1d6kr6rf3j7 CreatedAt:2025-04-21T12:11:32Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:0 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithNewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:900 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:BALANCE ProjectName:default ScalingGroupId:scg-ydu5dwe4nnd6kqpbsbuc ScalingGroupName:test_e9aef648-ed16-4807-b294-3118cbb94430 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-2fe72h3r8pr7k59gp68yogx1p subnet-12bhi1j0k4buo17q7y2aet40a] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-25T07:34:48Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn] map[ActiveScalingConfigurationId:scc-ydu5cvr4go7h70rs17oq CreatedAt:2025-04-21T11:55:51Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:0 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithNewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:900 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-ydu5cvobb67h7110nsqr ScalingGroupName:test_make_effort_to_provision_esi_instance_auto_scaling0 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-2fe72h3r8pr7k59gp68yogx1p subnet-in29bofzzfuo8gbssxhpj6pr] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-27T07:50:29Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn] map[ActiveScalingConfigurationId: CreatedAt:2025-04-21T09:12:38Z DBInstanceIds:[] DefaultCooldown:300 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:0 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithOldestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId:lt-ydu521mjhd4pf5w7iffd LaunchTemplateOverrides:[] LaunchTemplateVersion:Default LifecycleState:InActive LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:900 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:PRIORITY ProjectName:default ScalingGroupId:scg-ydu529hknc7h711wnzt7 ScalingGroupName:任华西-esi-segmented ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-in29bofzzfuo8gbssxhpj6pr] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-21T09:12:38Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn] map[ActiveScalingConfigurationId: CreatedAt:2025-04-21T09:03:03Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:0 HealthCheckType:ECS InstanceTerminatePolicy:OldestScalingConfigurationWithOldestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId:lt-ydt96663gx4pf62xh0w1 LaunchTemplateOverrides:[] LaunchTemplateVersion:Default LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:900 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:BALANCE ProjectName:default ScalingGroupId:scg-ydu51n3ag57h71541h5j ScalingGroupName:test_make_effort_to_provision_esi_instance_with_modify_policy_auto_scaling0 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-in29bofzzfuo8gbssxhpj6pr] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-22T07:14:04Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn] map[ActiveScalingConfigurationId:scc-ydtx5nu76w7h70wslv7c CreatedAt:2025-04-18T08:16:10Z DBInstanceIds:[] DefaultCooldown:5 DesireCapacity:-1 DesireCapacityType:units DesireInstanceNumber:0 HealthCheckType:ECS InstanceTerminatePolicy:NewestInstance InstancesDistribution:map[CompensateWithOnDemand:false OnDemandBaseCapacity:0 OnDemandPercentageAboveBaseCapacity:0 SpotInstanceRemedy:false] LaunchTemplateId: LaunchTemplateOverrides:[] LaunchTemplateVersion: LifecycleState:Active LoadBalancerHealthCheckGracePeriod:300 MaxInstanceNumber:10 MaxSize:0 MinInstanceNumber:0 MinSize:0 MultiAZPolicy:BALANCE ProjectName:default ScalingGroupId:scg-ydtx5nssrpd6ksegkwyp ScalingGroupName:test_create_alarm_policy_and_specify_effective_time_auto_scaling0 ScalingMode:release ServerGroupAttributes:[] StoppedCapacity:0 StoppedInstanceCount:0 SubnetIds:[subnet-imc2pmpasbuo8gbssz4tv3cw] SuspendedProcesses:[] Tags:[] TotalCapacity:0 TotalInstanceCount:0 UpdatedAt:2025-04-21T06:05:49Z VpcId:vpc-2ff4fh7wic2dc59gp67u70mpn]] TotalCount:19]]
如果通过如下“美化”,可以输出到按照最初给出实例一样展示出来
jsonData, _ := json.MarshalIndent(output, "", " ")fmt.Println(string(jsonData))
json.MarshalIndent(output, "", " ")
-
将 Go 的结构体(或任意可序列化的值)
output
转换成 格式化后的 JSON 字符串。 -
第二个参数是前缀(通常设为
""
),第三个参数是每层缩进的字符串(这里是两个空格" "
)。 -
返回的是一个
[]byte
类型的 JSON 数据。 -
将[]byte类型的JSON数据转换成go中的string类型,方便控制台输出用于调试。
json.MarshalIndent(...) + Println | 打印结构,用于调试 |
2.完全解析到结构体
参考上面的JSON响应,我们需要定义与之对应的结构体
// ResponseMetadata 定义响应元数据部分
type ResponseMetadata struct {Action string `json:"Action"`Region string `json:"Region"`RequestId string `json:"RequestId"`Service string `json:"Service"`Version string `json:"Version"`
}// InstancesDistribution 定义实例分布信息
type InstancesDistribution struct {CompensateWithOnDemand bool `json:"CompensateWithOnDemand"`OnDemandBaseCapacity int `json:"OnDemandBaseCapacity"`OnDemandPercentageAboveBaseCapacity int `json:"OnDemandPercentageAboveBaseCapacity"`SpotInstanceRemedy bool `json:"SpotInstanceRemedy"`
}// Tag 定义标签信息
type Tag struct {Key string `json:"Key"`Value string `json:"Value"`
}// ScalingGroup 定义伸缩组信息
type ScalingGroup struct {ActiveScalingConfigurationId string `json:"ActiveScalingConfigurationId"`CreatedAt string `json:"CreatedAt"`DBInstanceIds []string `json:"DBInstanceIds"`DefaultCooldown int `json:"DefaultCooldown"`DesireCapacity int `json:"DesireCapacity"`DesireCapacityType string `json:"DesireCapacityType"`DesireInstanceNumber int `json:"DesireInstanceNumber"`HealthCheckType string `json:"HealthCheckType"`InstanceTerminatePolicy string `json:"InstanceTerminatePolicy"`InstancesDistribution InstancesDistribution `json:"InstancesDistribution"`LaunchTemplateId string `json:"LaunchTemplateId"`LaunchTemplateOverrides []interface{} `json:"LaunchTemplateOverrides"`LaunchTemplateVersion string `json:"LaunchTemplateVersion"`LifecycleState string `json:"LifecycleState"`LoadBalancerHealthCheckGracePeriod int `json:"LoadBalancerHealthCheckGracePeriod"`MaxInstanceNumber int `json:"MaxInstanceNumber"`MaxSize int `json:"MaxSize"`MinInstanceNumber int `json:"MinInstanceNumber"`MinSize int `json:"MinSize"`MultiAZPolicy string `json:"MultiAZPolicy"`ProjectName string `json:"ProjectName"`ScalingGroupId string `json:"ScalingGroupId"`ScalingGroupName string `json:"ScalingGroupName"`ScalingMode string `json:"ScalingMode"`ServerGroupAttributes []interface{} `json:"ServerGroupAttributes"`StoppedCapacity int `json:"StoppedCapacity"`StoppedInstanceCount int `json:"StoppedInstanceCount"`SubnetIds []string `json:"SubnetIds"`SuspendedProcesses []interface{} `json:"SuspendedProcesses"`Tags []Tag `json:"Tags"`TotalCapacity int `json:"TotalCapacity"`TotalInstanceCount int `json:"TotalInstanceCount"`UpdatedAt string `json:"UpdatedAt"`VpcId string `json:"VpcId"`
}// Result 定义结果部分
type Result struct {PageNumber int `json:"PageNumber"`PageSize int `json:"PageSize"`ScalingGroups []ScalingGroup `json:"ScalingGroups"`
}// Response 定义整个响应结构
type Response struct {ResponseMetadata ResponseMetadata `json:"ResponseMetadata"`Result Result `json:"Result"`
}
使用上面的结构体查询并遍历最终的结果
func DescribeScalingGroups(session *session.Session) {// 构建自定义GET请求universalReq := universal.RequestUniversal{ServiceName: "auto_scaling",Action: "DescribeScalingGroups",Version: "2020-01-01",HttpMethod: universal.GET,}// 创建自定义GET客户端universal := universal.New(session)// 目标 ScalingGroupIdtargetId := "scg-ydu51n3ag57h71541h5j"// 指定参数形式parameters := map[string]interface{}{"ScalingGroupIds.1": targetId,}output, err := universal.DoCall(universalReq, ¶meters)if err != nil {panic(err)}fmt.Println(*output)// 假设 output 是从 DoCall 返回的 *Response 类型// jsonData, _ := json.MarshalIndent(output, "", " ")// fmt.Println(string(jsonData))// 将 output 映射到 Response 结构体var resp Responsedata, err := json.Marshal(output) // 将output 转换为 JSON 格式的字节流([]byte)if err != nil {panic(err)}err = json.Unmarshal(data, &resp) // 使用 json.Unmarshal 函数将上述得到的 JSON 字节流反序列化到 resp 变量中if err != nil {fmt.Println("Error unmarshalling JSON:", err)return}// 查找并打印 LifecycleStatefor _, group := range resp.Result.ScalingGroups {if group.ScalingGroupId == targetId {fmt.Printf("ScalingGroupId %s has LifecycleState: %s\n", targetId, group.LifecycleState)return}}fmt.Printf("ScalingGroupId %s not found.\n", targetId)}
3.简化解析到结构体
我们发现我们只需要比如ScalingGroupId和LifecycleState,甚至是部分的Metadata元数据,其他的很多数据都不需要使用,“感觉”没有必要定义。这个感觉是对的,很多语言就是这样,编程语言是面向人的,给机器使用的。
// ResponseMetadata 定义响应元数据部分,如果不需要可以省略或简化
type ResponseMetaData struct {Action string `json:"Action"`Region string `json:"Region"`Request string `json:"Request"`
}// ScalingGroup,只定义需要的字段
type ScalingGroup struct {ScalingGroupId string `json:"ScalingGroupId"`LifecycleState string `json:"LifecycleState"`
}// 定义结果部分
type Result struct {ScalingGroups []ScalingGroup `json:"ScalingGroups"`
}// 定义整个响应结构
type Response struct {ResponseMetaData ResponseMetaData `json:"ResponseMetaData"`Result Result `json:"Result"`
}
封装查询接口
func DescribeScalingGroups(session *session.Session) {// 构建自定义GET请求universalReq := universal.RequestUniversal{ServiceName: "auto_scaling",Action: "DescribeScalingGroups",Version: "2020-01-01",HttpMethod: universal.GET,}// 创建自定义GET客户端universal := universal.New(session)// 发起请求并处理返回或异常parameters := make(map[string]interface{})output, err := universal.DoCall(universalReq, ¶meters)if err != nil {panic(err)}fmt.Println(*output)// 假设 output 是从 DoCall 返回的 *Response 类型// jsonData, _ := json.MarshalIndent(output, "", " ")// fmt.Println(string(jsonData))// 将 output 映射到 Response 结构体var resp Responsedata, err := json.Marshal(output) // 将output 转换为 JSON 格式的字节流([]byte)if err != nil {panic(err)}err = json.Unmarshal(data, &resp) // 使用 json.Unmarshal 函数将上述得到的 JSON 字节流反序列化到 resp 变量中if err != nil {fmt.Println("Error unmarshalling JSON:", err)return}// 目标 ScalingGroupIdtargetId := "scg-ydu51n3ag57h71541h5j"// 查找并打印 LifecycleStatefor _, group := range resp.Result.ScalingGroups {if group.ScalingGroupId == targetId {fmt.Printf("ScalingGroupId %s has LifecycleState: %s\n", targetId, group.LifecycleState)return}}fmt.Printf("ScalingGroupId %s not found.\n", targetId)}
4.解析到interface
我们知道Interface{}可以用来存储任何类型的对象,这样数据结构正好可以存储解析繁琐嵌套的JSON结果,JSON包中采用的map[string]interface{}和[]interface{}结构来存储任意的JSON对象和数组。所以任何结构我们都可以定义并解析到Interface{}里面
response := []byte(`{"RequestId":"202504291928461ADFGHJKCD8A4862","Action":"DescribeScalingGroups","ScalingGroups":["scalingGroupId1","scalingGroupId2"]}`)var f interface{}
err := json.Unmarshal{response, &b}
这个时候f里面就存储了一个map类型,他们的key是string,值存储在空的interface{}中的
f = map[string]interface{}{"RequestId":"202504291928461ADFGHJKCD8A4862","Action":"DescribeScalingGroups","ScalingGroups":[]interface{}{"scalingGroupId1","scalingGroupId2",},
}
那如何来访问需要的LifecycleState字段呢,可以通过断言的方式
m := f.(map[string]interface{})
接着给出示例
func DescribeScalingGroups(session *session.Session) {// 构建自定义GET请求universalReq := universal.RequestUniversal{ServiceName: "auto_scaling",Action: "DescribeScalingGroups",Version: "2020-01-01",HttpMethod: universal.GET,}// 创建自定义GET客户端universal := universal.New(session)// 发起请求并处理返回或异常parameters := make(map[string]interface{})output, err := universal.DoCall(universalReq, ¶meters)if err != nil {panic(err)}fmt.Println(*output)// 假设 output 是从 DoCall 返回的 *Response 类型// jsonFormateData, _ := json.MarshalIndent(output, "", " ")// fmt.Println(string(jsonFormateData))// 查找并打印 LifecycleStatejsonData, err := json.Marshal(output) // 将output 转换为 JSON 格式的字节流([]byte)if err != nil {panic(err)}var x interface{}err = json.Unmarshal(jsonData, &x)if err != nil {fmt.Println("Error unmarshalling JSON:", err)return}fmt.Println("x contains: ", x)fmt.Println("===============")// 类型断言为 map[string]interface{}m := x.(map[string]interface{})// 访问 Result 下的 ScalingGroupsresult := m["Result"].(map[string]interface{})scalingGroups := result["ScalingGroups"].([]interface{})// 目标 ScalingGroupIdtargetId := "scg-ydu51n3ag57h71541h5j"// 查找并打印 LifecycleStatefor _, item := range scalingGroups {group := item.(map[string]interface{})scalingGroupId := group["ScalingGroupId"].(string)lifecycleState := group["LifecycleState"].(string)if scalingGroupId == targetId {fmt.Printf("ScalingGroupId %s has LifecycleState: %s\n", targetId, lifecycleState)return}}fmt.Printf("ScalingGroupId %s not found.\n", targetId)}
4.使用第三方包SimpleJSON
既然要使用第三方的包,需要先安装
go get "github.com/bitly/go-simplejson"
这里直接给出示例
func DescribeScalingGroups(session *session.Session) {// 构建自定义GET请求universalReq := universal.RequestUniversal{ServiceName: "auto_scaling",Action: "DescribeScalingGroups",Version: "2020-01-01",HttpMethod: universal.GET,}// 创建自定义GET客户端universal := universal.New(session)// 发起请求并处理返回或异常parameters := make(map[string]interface{})output, err := universal.DoCall(universalReq, ¶meters)if err != nil {panic(err)}fmt.Println(*output)// 假设 output 是从 DoCall 返回的 *Response 类型// jsonData, _ := json.MarshalIndent(output, "", " ")// fmt.Println(string(jsonData))// 查找并打印 LifecycleStatedata, err := json.Marshal(output) // 将output 转换为 JSON 格式的字节流([]byte)if err != nil {panic(err)}// Step 2: 用 simplejson 解析simpleJsonData, err := simplejson.NewJson(data)if err != nil {fmt.Println("Failed to parse JSON:", err)return}// Step 3: 查找目标 ScalingGroupIdtargetId := "scg-ydu51n3ag57h71541h5j"scalingGroups, err := simpleJsonData.Get("Result").Get("ScalingGroups").Array()if err != nil {fmt.Println("Error getting ScalingGroups array:", err)return}for _, item := range scalingGroups {group := item.(map[string]interface{})scalingGroupId := group["ScalingGroupId"].(string)lifecycleState := group["LifecycleState"].(string)if scalingGroupId == targetId {fmt.Printf("Found LifecycleState: %s\n", lifecycleState)return}}}
5.编解码
5.1 Marshal*
上文中看到了Marshal()和MarshalIndent()函数可以将数据封装成json数据。
- struct、slice、array、map都可以转换成json
- struct转换成json的时候,只有字段首字母大写的才会被转换
- map转换的时候,key必须为string
- 封装的时候,如果是指针,会追踪指针指向的对象进行封装
先有数据结构,然后Marshal。JSON包里Marshal函数来处理,函数定义如下:
func Marshal(v interface{}) ([]byte, error)
package mainimport ("encoding/json""fmt"
)type Server struct {ServerName stringServerIP string
}type Serverslice struct {Servers []Server
}func main() {var s Serverslices.Servers = append(s.Servers, Server{ServerName: "ecs", ServerIP: "127.0.0.1"})s.Servers = append(s.Servers, Server{ServerName: "auto_scaling", ServerIP: "127.0.0.2"})b, err := json.Marshal(s)if err != nil {fmt.Println("json err:", err)}fmt.Println(string(b))
}
输出结果如下所示:
{"Servers":[{"ServerName":"ecs","ServerIP":"127.0.0.1"},{"ServerName":"auto_scaling","ServerIP":"127.0.0.2"}]}
5.2 json.NewEncoder和json.NewDecoder
除了marshal和unmarshal函数,Go还提供了Decoder和Encoder对streamJSON进行处理,常见 request中的Body、文件等。
// 编码
json.NewEncoder(<Writer>).encode(v)
json.Marshal(&v)// 解码
json.NewDecoder(<Reader>).decode(&v)
json.Unmarshal([]byte, &v)
5.3 Marshal vs jons.New*coder
package mainimport ("encoding/json""fmt""bytes""strings"
)type Person struct {Name string `json:"name"`Age int `json:"age"`
}func main() {// 1. 使用 json.Marshal 编码person1 := Person{"zhangsan", 35}bytes1, err := json.Marshal(&person1)if err == nil {// 返回的是字节数组 []bytefmt.Println("json.Marshal 编码结果: ", string(bytes1))}// 2. 使用 json.Unmarshal 解码str := `{"name":"lisi","age":35}`// json.Unmarshal 需要字节数组参数, 需要把字符串转为 []byte 类型bytes2 := []byte(str) // 字符串转换为字节数组var person2 Person // 用来接收解码后的结果if json.Unmarshal(bytes2, &person2) == nil {fmt.Println("json.Unmarshal 解码结果: ", person2.Name, person2.Age)}// 3. 使用 json.NewEncoder 编码person3 := Person{"wangwu", 35}// 编码结果暂存到 bufferbytes3 := new(bytes.Buffer)_ = json.NewEncoder(bytes3).Encode(person3)if err == nil {fmt.Print("json.NewEncoder 编码结果: ", string(bytes3.Bytes()))}// 4. 使用 json.NewDecoder 解码str4 := `{"name":"lier","age":34}`var person4 Person// 创建一个 string reader 作为参数err = json.NewDecoder(strings.NewReader(str4)).Decode(&person4)if err == nil {fmt.Println("json.NewDecoder 解码结果: ", person4.Name, person4.Age)}
}