通过遍历AST从嵌套结构数组中获取结构名称

问题描述

我正在使用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"`

我需要访问CurrentStateInstanceIDPrevIoUsstate,以便可以将它们保存在配置中。获取顶级结构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字段,例如CodeName

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 (将#修改为@)