Maison >développement back-end >Golang >Ajout de paramètres de requête de filtre dans Go Huma

Ajout de paramètres de requête de filtre dans Go Huma

Patricia Arquette
Patricia Arquetteoriginal
2024-12-07 04:38:16686parcourir

D'après ce que j'ai pu découvrir, Huma ne prend malheureusement pas en charge les filtres de requête de tableau comme celui-ci : filters[]=filter1&filters[]=filter2 (sans laisser les crochets de côté, par exemple filter=filter1&filter=filter2). Je suis tombé sur ce problème Github qui donne un exemple de séparation des filtres par virgule https://github.com/danielgtaylor/huma/issues/325, c'est donc ce que nous avons fini par faire : filters=postcode:eq:RM7(EX, créé : gt : 2024-01-01

Documenter les filtres

Contrairement aux paramètres du corps, que l'on peut simplement spécifier en tant que structures et qui sont ensuite à la fois validés et générés dans la documentation, la documentation et la validation des filtres doivent être effectuées séparément.

La documentation peut simplement être ajoutée sous l'attribut description de l'objet Huma.Param (sous Opération) :

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

Nous pouvons maintenant définir notre structure PropertyFilterParams pour validation :

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
}

J'ai ajouté PropertyFilterParams à la structure 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"`
}

Voici à quoi ressemble l'ajout de PropertyQueryParams à la route (notez que le code d'opération lui-même, y compris la description du filtre, se trouve sous getAllPropertyOperation - je n'ai pas collé le code complet pour cela, mais j'espère que vous en comprenez l'essentiel) . Si la validation échoue, elle générera une réponse 422. J'ai également ajouté comment nous pouvons parcourir les valeurs de filtre qui ont été transmises :

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
        })
}

J'espère que cela aidera quelqu'un. Faites-moi savoir dans les commentaires si vous avez trouvé une meilleure solution.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn