首頁 > 後端開發 > Golang > 將 AWS redshiftdataapiservice.GetStatementResultOutput 轉換為 JSON 或結構

將 AWS redshiftdataapiservice.GetStatementResultOutput 轉換為 JSON 或結構

王林
發布: 2024-02-06 10:54:04
轉載
537 人瀏覽過

将 AWS redshiftdataapiservice.GetStatementResultOutput 转换为 JSON 或结构

問題內容

我有一個 AWS Redshift Serverless 資料庫,我正在透過 AWS Go SDK 的 redshiftdataapiservice 查詢該資料庫。查詢和所有這些都有效,但記錄以難以使用/理解的格式傳回。

我的程式碼是這樣的:

import (
    "fmt"
    "log"
    "time"
    "os"
    "context"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/redshiftdata"
    "github.com/aws/aws-sdk-go-v2/service/redshiftdata/types"
)

// Execute a Redshift query and return a result statement output
func executeRedshiftQuery(sql string) (*redshiftdata.GetStatementResultOutput, error) {
    // Load the Shared AWS Configuration (~/.aws/config)
    cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(os.Getenv("AWS_REGION")))
    if err != nil {
        return nil, err
    }

    // Create a service client
    redshiftclient := redshiftdata.NewFromConfig(cfg)
    execStmt, err := redshiftclient.ExecuteStatement(context.TODO(), &redshiftdata.ExecuteStatementInput{
        WorkgroupName: aws.String(os.Getenv("WG_NAME")),
        Database:      aws.String(os.Getenv("DB_NAME")),
        Sql:           aws.String(sql),
    })
    if err != nil {
        return nil, err
    }

    // wait for query to finish
    for {
        descStmt, err := redshiftclient.DescribeStatement(context.TODO(), &redshiftdata.DescribeStatementInput{
            Id: execStmt.Id,
        })
        if err != nil {
            return nil, err
        }

        // return an error if the query failed or aborted
        if descStmt.Status == types.StatusStringFailed || descStmt.Status == types.StatusStringAborted {
            err := errors.New("the Redshift query failed or was aborted")
            return nil, err
        } else if descStmt.Status != types.StatusStringFinished {
            time.Sleep(1 * time.Second)
            continue
        }

        break
    }

    // get the results
    resultStmt, err := redshiftclient.GetStatementResult(context.TODO(), &redshiftdata.GetStatementResultInput{
        Id: execStmt.Id,
    })
    if err != nil {
        return nil, err
    }

    return resultStmt, nil
}
登入後複製

我發現 *Fields 的二維陣列很難處理。我如何(最好是簡單地)將其映射到可用的 JSON,或者說類型結構數組?或者有沒有辦法從 Redshift 請求 JSON?如果可能的話,我想將所有這些完全保留在我的 Golang 應用程式中。


正確答案


我沒有找到官方方法,但下面的方法是透過建立列名稱到列值的對應片段,然後從那裡解組來運作。

// Extracts the column name from column metadata for a given column index
func getColumnName(metadata []types.ColumnMetadata, index int) string {
    if index < len(metadata) {
        // We assume the metadata is in the same order as the columns in the record.
        // If the column name is not set or empty, we can fallback to a default naming convention.
        if metadata[index].Name != nil {
            return *metadata[index].Name
        }
        return fmt.Sprintf("column_%d", index)
    }
    // Fallback if the index is out of range of the metadata slice.
    return fmt.Sprintf("unknown_column_%d", index)
}

// Converts query results to JSON bytes for easy unmarshaling to structs
func queryResultsToJSON(query_results *redshiftdata.GetStatementResultOutput) ([]byte, error) {
    // Convert the records to a slice of maps for JSON conversion
    var records []map[string]interface{}

    for _, row := range query_results.Records {
        record := make(map[string]interface{})
        for idx, col := range row {
            // Use the column metadata to determine the name of the column
            columnName := getColumnName(query_results.ColumnMetadata, idx)

            // Check the type of the value and assign it to the record map
            var value interface{}
            switch v := col.(type) {
            case *types.FieldMemberBlobValue:
                value = v.Value
            case *types.FieldMemberBooleanValue:
                value = v.Value
            case *types.FieldMemberDoubleValue:
                value = v.Value
            case *types.FieldMemberIsNull:
                value = nil
            case *types.FieldMemberLongValue:
                value = v.Value
            case *types.FieldMemberStringValue:
                value = v.Value
            }
            record[columnName] = value
        }
        records = append(records, record)
    }

    // Marshal the records to JSON
    jsonBytes, err := json.Marshal(records)
    if err != nil {
        log.Error("failed to marshal records to JSON, " + err.Error())
        return nil, err
    }

    return jsonBytes, nil
}
登入後複製

以上是將 AWS redshiftdataapiservice.GetStatementResultOutput 轉換為 JSON 或結構的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板