Go语言 使用两个可能的名称进行输入字段验证

u4dcyp6a  于 2023-09-28  发布在  Go
关注(0)|答案(2)|浏览(80)

我正在迁移一个最初用Python编写的API。Python API允许你以camelCase或snake_case的形式发送请求,如下所示:
这是允许

{
    "someInput": "nice"
}

这是允许

{
    "some_input": "nice"
}

这是使用一个很棒的Python库完成的:皮丹蒂克

from pydantic import BaseModel

def to_camel(string):
    words = string.split('_')
    return words[0] + ''.join(word.capitalize() for word in words[1:])

class InputModel(BaseModel):
    some_input: str

    class Config:
        alias_generator = to_camel
        allow_population_by_field_name = True

这允许通过别名(someInput)或字段名(some_input)创建InputModel。我想在Go中做同样的或等效的事情。我在用Gin:

func Routes(router *gin.Engine) {
    v1 := router.Group("/v1")
    {
        v1.POST("/shipments", controllers.ShipmentCreator)
    }
}

func ShipmentCreator(ctx *gin.Context) {
    ResponseController := new(internal.OutputModel)
    var body domain.ShipmentsInputModel
    if err := ctx.BindJSON(&body); err != nil {
        fmt.Println(err)
    }
    validate := validator.New()
    err := validate.Struct(body)
    if err != nil {
        var validationErrors validator.ValidationErrors
        errors.As(err, &validationErrors)
        for _, validationError := range validationErrors {
            ResponseController.AddError(internal.ErrorsModel{
                Parameter: validationError.Field(),
                Message:   validationError.Error(),
            })
        }
        ctx.JSON(http.StatusBadRequest, ResponseController)
        return
    }

我的输入结构看起来像这样:

type ShipmentsInputModel struct {
    LotId   string   `json:"lotId" tag:"lot_id" alias:"lot_id" validate:"required"`
}

当我的输入是:

{
   "lot_id": "someLotId"
}

它返回:

"message": "Key: 'ShipmentsInputModel.LotId' Error:Field validation for 'LotId' failed on the 'required' tag",

如何同时接受camelCase和snake_case?

e4yzc0pl

e4yzc0pl1#

实际上有一种方法可以在Gin中使用struct filed标记中的binding标记来验证具有两个可能名称的输入,这允许您为同一字段指定多个键,作为示例,请参见下面的示例:

type ShipmentsInputModel struct {
LotId string `json:"lotId" json:"lot_id" binding:"required,lotId|lot_id"`
}

要了解有关验证和绑定的更多信息,请阅读此https://gin-gonic.com/docs/examples/binding-and-validation/

vwhgwdsa

vwhgwdsa2#

在Go语言中,你不能为一个struct字段同时提供两个JSON标签。JSON标记是使用单个字符串指定的,它们用于定义字段应如何封送(序列化为JSON)或取消封送(从JSON反序列化)。不能直接为结构中的单个字段指定多个标记。
如果需要在JSON输出中同时支持CamelCase和SnakeCase,通常必须为结构字段选择一个一致的命名约定,然后为所有字段使用适当的JSON标记。
有一个很好的方法。我希望这能帮上忙。

package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type ShipmentsInputModel struct {
        LotID
    }
    
    type LotID struct {
        LotId  string `json:"lotId,omitempty"`
        Lot_ID string `json:"lot_id,omitempty"`
    }
    
    func (s *ShipmentsInputModel) setLodID(id string) {
        s.LotId = id
        s.Lot_ID = id
    }
    
    func main() {
        shipment := ShipmentsInputModel{}
        shipment.setLodID("someLotID")
    
        // Convert struct to JSON
        jsonData, err := json.Marshal(shipment)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        // prints: {"lotId":"someLotID","lot_id":"someLotID"}
        fmt.Println(string(jsonData))
    }

相关问题