首頁 >後端開發 >Golang >在 Go Huma 中加入過濾查詢參數

在 Go Huma 中加入過濾查詢參數

Patricia Arquette
Patricia Arquette原創
2024-12-07 04:38:16685瀏覽

據我所知,不幸的是,Huma 不支援這樣的陣列查詢過濾器:filters[]=filter1&filters[]=filter2(也不保留括號,例如filter=filter1&filter=filter2)。我遇到了這個Github 問題,它給出了一個用逗號分隔過濾器的範例https://github.com/danielgtaylor/huma/issues/325,所以這就是我們最終要做的:filters=postcode:eq: RM7(EX,建立時間:gt:2024-01-01

記錄過濾器

與主體參數不同,主體參數可以簡單地指定為結構,然後在文檔中對其進行驗證和生成,過濾器的文檔和驗證必須單獨完成。

文件可以簡單地加入 Huma.Param 物件的描述屬性下(在操作下):

Parameters: []*huma.Param{{
            Name: "filters",
            In:   "query",
            Description: "Filter properties by various fields. Separate filters by comma.\n\n" +
                "Format: field:operator:value\n\n" +
                "Supported fields:\n" +
                "- postcode (operator: eq)\n" +
                "- created (operators: gt, lt, gte, lte)\n",
            Schema: &huma.Schema{
                Type: "string",
                Items: &huma.Schema{
                    Type:    "string",
                    Pattern: "^[a-zA-Z_]+:(eq|neq|gt|lt|gte|lte):[a-zA-Z0-9-:.]+$",
                },
                Examples: []any{
                    "postcode:eq:RM7 8EX",
                    "created:gt:2024-01-01",
                },
            },
            Required: false,
        }},

Adding filter query parameters in Go Huma

我們現在可以定義 PropertyFilterParams 結構進行驗證:

type FilterParam struct {
    Field    string
    Operator string
    Value    interface{}
}

type PropertyFilterParams struct {
    Items []FilterParam
}

func (s *PropertyFilterParams) UnmarshalText(text []byte) error {
    equalityFields := []string{"postcode"}
    greaterSmallerFields := []string{}
    dateFields := []string{"created"}

    for _, item := range strings.Split(string(text), ",") {
        filterParam, err := parseAndValidateFilterItem(item, equalityFields, greaterSmallerFields, dateFields)
        if err != nil {
            return err
        }
        s.Items = append(s.Items, filterParam)
    }

    return nil
}

func (s *PropertyFilterParams) Schema(registry huma.Registry) *huma.Schema {
    return &huma.Schema{
        Type: huma.TypeString,
    }
}

func parseAndValidateFilterItem(item string, equalityFields []string, greaterSmallerFields []string, dateFields []string) (FilterParam, error) {
    parts := strings.SplitN(item, ":", 3)

    field := parts[0]
    operator := parts[1]
    value := parts[2]

    if contains(equalityFields, field) {
        if operator != "eq" && operator != "neq" {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Only 'eq' and 'neq' are supported.", operator, field)
        }
    } else if contains(greaterSmallerFields, field) {
        if !validation.IsValidCompareGreaterSmallerOperator(operator) {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Supported operators: eq, neq, gt, lt, gte, lte.", operator, field)
        }
    } else if contains(dateFields, field) {
        if !validation.IsValidCompareGreaterSmallerOperator(operator) {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Supported operators: eq, neq, gt, lt, gte, lte.", operator, field)
        }
        if !validation.IsValidDate(value) {
            return FilterParam{}, fmt.Errorf("Invalid date format: %s. Expected: YYYY-MM-DD", value)
        }
    } else {
        return FilterParam{}, fmt.Errorf("Unsupported filter field: %s", field)
    }

    return FilterParam{Field: field, Operator: operator, Value: value}, nil
}

我將 PropertyFilterParams 加入到 PropertyQueryParams 結構中:

type PropertyQueryParams struct {
    PaginationParams
    Filter PropertyFilterParams `query:"filters" doc:"Filter properties by various fields"`
    Sort   PropertySortParams   `query:"sorts" doc:"Sort properties by various fields"`
}

這就是將 PropertyQueryParams 添加到路由的樣子(請注意,操作代碼本身,包括過濾器描述,位於 getAllPropertyOperation 下 - 我沒有粘貼完整的代碼,但希望您能理解它的要點) 。如果驗證失敗,它將拋出 422 個回應。我還添加瞭如何循環遍歷通過的過濾器值:

huma.Register(api, getAllPropertyOperation(schema, "get-properties", "/properties", []string{"Properties"}),
        func(ctx context.Context, input *struct {
            models.Headers
            models.PropertyQueryParams
        }) (*models.MultiplePropertyOutput, error) {

            for _, filter := range input.Filter.Items {
                fmt.Println(filter)
            }

            return mockMultiplePropertyResponse(), err
        })
}

我希望這對某人有幫助。如果您找到更好的解決方案,請在評論中告訴我。

以上是在 Go Huma 中加入過濾查詢參數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn