Skip to content

Solving the binding problem from an array of numeric strings to an int64 slice in the Gin framework ​

In actual development, we often encounter the situation where the client passes an array of numbers in string format, while the server needs to bind it to an int64 slice. This article will explain in detail how to elegantly solve this problem using the Gin framework.

Problem Background ​

When using the Gin framework for JSON binding, if the client passes numbers in string array format (e.g.{"ids": ["1641850092312858666", "1641850092312858667"]}), while the server-side struct defines []int64 type, you will encounter the following error:

txt
Error #01: json: cannot unmarshal string into Go struct field RequiredIdsInt64Params.ids of type int64

Solution ​

Custom type Int64Slice ​

We can do this by defining a custom type.Int64Slice and implement json.Unmarshaler Interface to solve this problem:

go
// Int64Slice is a custom type used to handle the conversion from a string array to an int64 array
// swagger:type []int64 [28994660812304,28994660812305]
type Int64Slice []int64

// UnmarshalJSON implements custom JSON deserialization logic
func (i *Int64Slice) UnmarshalJSON(data []byte) error {
    // First, try to parse the data as a string array
    var strSlice []string
    if err := json.Unmarshal(data, &strSlice); err != nil {
        return err
    }

    // Convert a string array to an int64 array
    var intSlice Int64Slice
    for _, str := range strSlice {
        intVal, err := strconv.ParseInt(str, 10, 64)
        if err != nil {
            return err
        }
        intSlice = append(intSlice, intVal)
    }

    // Assign the converted int64 array to Int64Slice
    *i = intSlice
    return nil
}

// MarshalJSON implements custom JSON serialization logic.
func (i Int64Slice) MarshalJSON() ([]byte, error) {
    // Convert an int64 array to a string array
    var strSlice []string
    for _, val := range i {
        strSlice = append(strSlice, strconv.FormatInt(val, 10))
    }

    // Serialize a string array into JSON
    return json.Marshal(strSlice)
}

Use custom types ​

When defining a struct, use our custom type:

go
type RequiredIdsInt64Params struct {
    // Ids.
    //
    // required: true
    // example: ["1641850092312858666", "1641850092312858667"]
    Ids Int64Slice `json:"ids" binding:"required" form:"ids" uri:"ids"`
}

Binding example ​

go
func HandleRequest(ctx *gin.Context) {
    var params RequiredIdsInt64Params
    if err := ctx.ShouldBindJSON(&params); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // Now params.Ids is already the correct []int64 type.
    fmt.Printf("Received IDs: %v\n", params.Ids)
}

Solution advantages ​

  • Type safety: Ensure that the received data is a valid int64 type

  • Error handling: Automatically handles conversion from string to int64 and provides error checking

  • Bidirectional support: Also implements the MarshalJSON method, supporting serialization back to string format

  • Swagger compatible Ensure API documentation displays correctly through comments.

  • Reusability This custom type can be reused throughout the project.

Other precautions ​

  • Performance considerations: For very large arrays, consider preallocating slice capacity.

  • error message: You can customize more user-friendly error messages

  • Boundary check: Additional validation of the numeric range can be added

Summary ​

By implementing custom types and JSON serialization/deserialization interfaces, we can elegantly solve the binding problem from string arrays to int64 slices in the Gin framework. This approach both maintains code cleanliness and provides good type safety and error handling mechanisms.

This pattern is not only applicable to the int64 type but can also be generalized to other type conversion scenarios that require special handling.

Last updated on11/07/2026, 02:16 PM
@fishfinal | @fishfinals | [email protected]