Skip to content

Comments

Add REST API response pattern package with multi-format support and i18n#6

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-api-response-pattern-readme
Draft

Add REST API response pattern package with multi-format support and i18n#6
Copilot wants to merge 3 commits intomainfrom
copilot/add-api-response-pattern-readme

Conversation

Copy link
Contributor

Copilot AI commented Nov 8, 2025

Implements a framework-agnostic REST API response pattern library supporting multiple standard formats (Envelope, Flat, Lean, HAL, Validation) with built-in internationalization for validation errors.

Package Structure

  • Response formats: Envelope (enterprise), Flat (lightweight), Lean (minimal), HAL (hypermedia), Validation (field errors)
  • i18n: Multi-language validation using go-playground/validator/v10 with EN/VI translations
  • Builder: Format-aware response writer with query parameter support
  • Type-safe: Go generics for compile-time safety

Usage

import "github.com/laziness-coders/go-utils/response"

// Framework-agnostic usage
func handler(w http.ResponseWriter, r *http.Request) {
    format := response.ParseFormat(r.URL.Query().Get("format"))
    lang := r.URL.Query().Get("lang")
    
    // Validation with i18n
    errors := response.ValidateStruct(req, lang)
    if len(errors) > 0 {
        response.WriteValidationError(w, 400, errors, format)
        return
    }
    
    // Success response
    response.WriteResponse(w, 200, data, nil, meta, format)
}

Format Examples

Envelope (?format=envelope):

{"success": true, "data": {...}, "meta": {...}}

Validation with Vietnamese (?lang=vi):

{
  "error": {
    "code": "INVALID_INPUT",
    "errors": [
      {"field": "Email", "message": "Email phải là giá trị email address"}
    ]
  }
}

Dependencies

Adds go-playground/validator/v10 ecosystem for validation and translation support.

Testing

47 test cases covering all formats and i18n scenarios (87.5% coverage).

Original prompt

Updated Question:
Please write a complete README.md that describes the flexible REST API response pattern solution (Envelope, Flat, Lean, HAL, Validation, i18n) so I can give it to Copilot to implement across multiple Go frameworks like Gin and Fiber.

Answer:
Here’s your ready-to-use README.md file 👇

🌐 Go REST API Response Pattern — Flexible and Framework-Agnostic

A clean, consistent, and extensible Result/Response Pattern for REST APIs in Go.
Supports multiple formats (Envelope, Flat, Lean, HAL, Validation) and works across frameworks like Gin, Fiber, Echo, etc.


🚀 Features

✅ Consistent and reusable response structure
✅ Supports multiple response formats:

  • Envelope – enterprise-style, predictable format
  • Flat – lightweight and human-readable
  • Lean – minimal and efficient
  • HAL – hypermedia (HATEOAS) style
  • Validation – rich field-level validation errors

✅ Internationalization (i18n) with multi-language support (e.g., English, Vietnamese)
✅ Compatible with any HTTP framework (Gin, Fiber, Echo, Chi, net/http)
✅ Easy to extend with custom error codes or metadata


🧱 Folder Structure Example

response/
│── envelope.go # Envelope format
│── flat.go # Flat format
│── lean.go # Lean format
│── hal.go # HAL format
│── validation.go # Validation format
│── builder.go # Common writer and helpers
│── i18n.go # Validator + translations


📦 Install Dependencies

go get github.com/go-playground/validator/v10
go get github.com/go-playground/locales
go get github.com/go-playground/universal-translator
go get github.com/go-playground/validator/v10/translations/en
go get github.com/go-playground/validator/v10/translations/vi


⸻

🧩 Core Response Models

1. Envelope Format (Default)

type Envelope[T any] struct {
    Success bool   `json:"success"`
    Data    T      `json:"data,omitempty"`
    Error   any    `json:"error,omitempty"`
    Meta    any    `json:"meta,omitempty"`
}

Example

{
  "success": true,
  "data": { "id": 1, "name": "Alice" },
  "meta": { "page": 1, "size": 10, "total": 30 }
}


⸻

2. Flat Format

type Flat[T any] struct {
    Status  string `json:"status"`   // "ok" | "error"
    Message string `json:"message"`
    Data    T      `json:"data,omitempty"`
}

Example

{ "status": "ok", "message": "Fetched successfully", "data": { "id": 1 } }


⸻

3. Lean Format

type OnlyData[T any] struct { Data T `json:"data"` }
type OnlyError struct { Error AppErr `json:"error"` }

Example

{ "data": { "id": 1, "name": "Alice" } }


⸻

4. HAL Format (Hypermedia)

type Link struct { Href string `json:"href"` }
type HAL[T any] struct {
    Links map[string]Link `json:"_links"`
    Data  T               `json:"data"`
}

Example

{
  "_links": {
    "self": { "href": "/v1/users/1" },
    "list": { "href": "/v1/users" }
  },
  "data": { "id": 1, "name": "Alice" }
}


⸻

5. Validation Format

type FieldError struct {
    Field   string `json:"field"`
    Message string `json:"message"`
}

type Validation struct {
    Code   string       `json:"code"` // e.g. INVALID_INPUT
    Errors []FieldError `json:"errors"`
}

Example

{
  "error": {
    "code": "INVALID_INPUT",
    "errors": [
      { "field": "email", "message": "must be valid email" },
      { "field": "password", "message": "min length 6" }
    ]
  }
}


⸻

🌍 Multi-Language Validation Setup

Step 1: Initialize the validator with translators

import (
    "github.com/go-playground/validator/v10"
    "github.com/go-playground/locales/en"
    "github.com/go-playground/locales/vi"
    ut "github.com/go-playground/universal-translator"
    en_trans "github.com/go-playground/validator/v10/translations/en"
    vi_trans "github.com/go-playground/validator/v10/translations/vi"
)

var (
    validate *validator.Validate
    uni      *ut.UniversalTranslator
)

func InitValidator() {
    validate = validator.New()
    uni = ut.New(en.New(), en.New(), vi.New())
}

Step 2: Detect and register language per request

func GetTranslator(lang string) ut.Translator {
    base := "en"
    if strings.HasPrefix(strings.ToLower(lang), "vi") {
        base = "vi"
    }
    trans, _ := uni.GetTranslator(base)
    if base == "vi" {
        vi_trans.RegisterDefaultTranslations(validate, trans)
    } else {
        en_trans.RegisterDefaultTranslations(validate, trans)
    }
    return trans
}

Step 3: Translate validation errors

func TranslateErrors(err error, trans ut.Translator) []FieldError {
    var out []FieldError
    if ves, ok := err.(validator.ValidationErrors); ok {
        for _, e := range ves {
            out = append(out, FieldError{Field: e.Field(), Message: e.Translate(trans)})
        }
    }
    return out
}


⸻

🧰 Common Writer / Response Builder

func WriteResponse[T any](w http.ResponseWriter, status int, data T, appErr *AppErr, meta any, format string) {
    switch format {
    case "flat":
        ...
    case...

</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 2 commits November 8, 2025 02:29
Co-authored-by: bos-hieu <9217908+bos-hieu@users.noreply.github.com>
Co-authored-by: bos-hieu <9217908+bos-hieu@users.noreply.github.com>
Copilot AI changed the title [WIP] Add README.md for flexible REST API response pattern Add REST API response pattern package with multi-format support and i18n Nov 8, 2025
Copilot AI requested a review from bos-hieu November 8, 2025 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants