如何获取AWS Policy类型定义?用Go结构体解析JSON策略
这确实是个实用的需求——用强类型结构体解析AWS IAM Policy,比用interface{}方便太多了!下面我一步步给你讲清楚怎么实现:
定义匹配AWS Policy的Go结构体
首先得贴合AWS IAM Policy的JSON结构来定义结构体,重点要处理Action字段的特殊情况:它既可以是单个字符串(比如s3:ListBucket),也可以是字符串数组。我们需要自定义类型来兼容这两种格式,同时处理嵌套的Condition结构。
import ( "encoding/json" "fmt" "strings" ) // 自定义Action类型,兼容单个字符串或字符串数组的JSON格式 type Action []string // 实现UnmarshalJSON方法,自动处理两种格式的转换 func (a *Action) UnmarshalJSON(data []byte) error { // 先尝试解析为单个字符串 var singleAction string if err := json.Unmarshal(data, &singleAction); err == nil { *a = []string{singleAction} return nil } // 若失败,再尝试解析为字符串数组 var multiActions []string if err := json.Unmarshal(data, &multiActions); err != nil { return err } *a = multiActions return nil } // Statement 对应Policy中的单个权限声明对象 type Statement struct { Sid string `json:"Sid,omitempty"` // omitempty表示空值时序列化会忽略该字段 Effect string `json:"Effect"` Action Action `json:"Action"` Resource string `json:"Resource"` Condition map[string]interface{} `json:"Condition,omitempty"` // 用通用map适配灵活的Condition结构 } // Policy 顶层的IAM Policy结构体 type Policy struct { Version string `json:"Version"` Statement []Statement `json:"Statement"` }
反序列化并直接访问字段
有了上面的结构体,你就可以直接把JSON字符串反序列化为Policy类型,然后像访问普通结构体字段一样操作它:
func main() { firstKey := `{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::amit", "Condition": { "StringLike": { "s3:prefix": "Development/*" } } }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": "arn:aws:s3:::amit/Development/*" } ] }` var policy Policy err := json.Unmarshal([]byte(firstKey), &policy) if err != nil { fmt.Printf("反序列化失败: %v\n", err) return } // 直接访问Version字段 fmt.Println("Policy版本:", policy.Version) // 遍历所有Statement并输出字段 for idx, stmt := range policy.Statement { fmt.Printf("\n第%d条权限声明:\n", idx+1) fmt.Println("生效规则:", stmt.Effect) fmt.Println("操作权限:", strings.Join(stmt.Action, ", ")) fmt.Println("资源ARN:", stmt.Resource) if stmt.Condition != nil { fmt.Println("附加条件:", stmt.Condition) } } }
关键细节说明
- 自定义Action类型:通过实现
UnmarshalJSON方法,我们把两种格式的Action统一转换成[]string,后续访问时不用再区分单个值还是数组,简化了逻辑。 - 结构体标签:
json:"Version"这类标签是告诉Go的JSON解析器,结构体字段对应JSON中的哪个键名;omitempty标签则是优化序列化行为(反序列化时不影响)。 - Condition字段:用
map[string]interface{}是因为AWS Policy的Condition结构非常灵活,不同的条件操作符(比如StringLike、NumericEquals)对应不同的嵌套结构。如果你的场景有固定的Condition格式,也可以定义更具体的结构体来替代通用map。
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

