问题描述
我正在使用AST从源文件中的结构生成json配置。这是所需配置的截断示例:
{
"actions": [
{
"actionName": "StopInstance","actionID": "","description": "","actionParams": [
{
"fieldName": "InstanceID","fieldType": {
"NamePos": 954,"Name": "string","Obj": null
},"fieldValue": "`json:\"instanceID\"`","dataSource": "event"
}
],"actionOutputs": [
{
"fieldName": "InstanceID","fieldType": {
"NamePos": 954,"Obj": null
},"fieldDataPath": "StoppingInstances.InstanceID"
},{
"fieldName": "Code","fieldType": {
"NamePos": 1151,"Name": "int","fieldValue": "`json:\"Code\"`","fieldDataPath": "StoppingInstances.CurrentState.Code"
},{
"fieldName": "Name","fieldType": {
"NamePos": 1180,"Obj": null
},"fieldValue": "`json:\"Name\"`","fieldDataPath": "StoppingInstances.CurrentState.Name"
}
]
}
]
}
我可以成功生成带有平面结构的配置。我在获取嵌套结构名称时遇到了麻烦。这些名称是正确组装配置所必需的。这是一个使用AWS EC2 API响应的结构示例:
type StopInstance struct {
StoppingInstances []struct {
CurrentState struct {
Code int `json:"Code"`
Name string `json:"Name"`
} `json:"CurrentState"`
InstanceID string `json:"InstanceId"`
PrevIoUsstate struct {
Code int `json:"Code"`
Name string `json:"Name"`
} `json:"PrevIoUsstate"`
} `json:"StoppingInstances"`
我需要访问CurrentState
,InstanceID
和PrevIoUsstate
,以便可以将它们保存在配置中。获取顶级结构StopInstance
的名称非常简单:
ast.Inspect(file,func(node ast.Node) bool {
t,ok := node.(*ast.typespec)
if !ok {
return true
}
if t.Type == nil {
return true
}
structName := t.Name.Name
}
我可以通过遍历节点来成功访问嵌套的struct字段,例如Code
和Name
:
ast.Inspect(file,ok := node.(*ast.typespec)
if !ok {
return true
}
if t.Type == nil {
return true
}
structName := t.Name.Name
s,ok := t.Type.(*ast.StructType)
if !ok {
return true
}
// Add outputs from actionData structs
for _,field := range s.Fields.List {
switch field.Type.(type) {
// Handle flat data structure
case *ast.StructType:
fieldName := field.Names[0].Name
fieldType := field.Type
fieldTag := field.Tag
output := ActionOutput{
FieldName: fieldName,FieldType: fieldType,FieldDataPath: fieldName,}
if t != nil {
output.FieldValue = fieldTag.Value
}
outputs = append(outputs,output)
// Handle nested data structures
case *ast.ArrayType:
parent := field.Names[0].Name
nestedOutputs,err := getnestedStructs(parent,file,node)
if err != nil {
log.Fatal(err)
}
}
}
func getnestedStructs(parentFieldName string,file *ast.File,node ast.Node) ([]ActionOutput,error) {
outputs := make([]ActionOutput,0)
ast.Inspect(file,func(n ast.Node) bool {
switch x := n.(type) {
case *ast.StructType:
for _,field := range x.Fields.List {
switch t := field.Type.(type) {
case *ast.Ident:
fieldName := field.Names[0].Name
fieldTag := field.Tag
output := ActionOutput{
FieldName: fieldName,FieldType: t,FieldDataPath: parentFieldName + "." + fieldName,}
if x != nil {
output.FieldValue = fieldTag.Value
}
outputs = append(outputs,output)
}
}
}
return true
})
return outputs,nil
}
我尝试遍历StoppingInstances
的字段列表。该列表不包括结构名称。没有type
关键字在结构前面的,似乎没有明确的方法可以通过AST获得结构名称。如何访问它们?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)