sqlc icon indicating copy to clipboard operation
sqlc copied to clipboard

Support automatically appending ,string to JSON tags for numeric types (e.g. BIGINT → int64 with json:",string")

Open LuoShenKui opened this issue 2 months ago • 2 comments

💡 Summary

Currently, sqlc does not provide a way to globally append ,string to JSON tags for numeric types like BIGINT while preserving the Go type as int64. This feature is important for frontend applications (e.g. JavaScript / TypeScript), which cannot safely handle 64-bit integers as numbers due to precision limitations.


🧠 Background / Problem

In modern frontend–backend setups, it's common to use JavaScript or TypeScript on the frontend. Since JavaScript numbers are IEEE 754 doubles, integers larger than 2^53 - 1 lose precision.

For example:

CREATE TABLE users (
  id BIGINT PRIMARY KEY,
  name TEXT
);

sqlc currently generates:

type User struct {
  ID   int64  `json:"id"`
  Name string `json:"name"`
}

If the id is 9007199254740993, the frontend will receive:

{ "id": 9007199254740992 }   // ❌ precision lost

The ideal JSON tag would be:

type User struct {
  ID   int64  `json:"id,string"`
  Name string `json:"name"`
}

This allows Go to keep using int64 internally (safe for arithmetic) while ensuring the frontend receives the value as a string, avoiding precision loss.


📌 Current Workarounds

  1. Per-column go_struct_tag overrides

    overrides:
      - column: "public.users.id"
        go_struct_tag: 'json:"id,string" db:"id"'
    

    ➡ Works, but is tedious when you have many bigint columns across many tables.

  2. Custom wrapper types (e.g. Int64String) Replace all BIGINT types with a custom Go type that implements MarshalJSON and UnmarshalJSON. ➡ Works globally, but requires additional type definitions and breaks the simplicity of using int64 directly.

There is currently no way to tell sqlc:

“For all BIGINT columns, keep the Go type as int64 but append ,string to the generated JSON tag.”


🚀 Proposed Solution

Add a new configuration option to globally append JSON tag suffixes (e.g. ,string) for specific DB types.

Example 1: New global option

gen:
  go:
    json_tag_suffix_for_types:
      - db_type: "pg_catalog.int8"
        suffix: ",string"

Example 2: Extend overrides to support JSON suffix

overrides:
  - db_type: "pg_catalog.int8"
    json_tag_suffix: ",string"

Expected generated code:

type User struct {
  ID   int64  `json:"id,string"`
  Name string `json:"name"`
}

Benefits

  • No need to define custom types just to get correct JSON output.
  • No need to write dozens or hundreds of per-column overrides.
  • Preserves int64 for arithmetic while fixing frontend precision issues.
  • Makes sqlc more ergonomic for modern web projects.

🧪 Environment

  • sqlc version: v1.28.0
  • Database: PostgreSQL
  • Language: Go
  • Use case: Backend API for JS/TS frontend

🙏 Thank you

This feature would make sqlc much more convenient for teams building modern web applications with PostgreSQL and Go.

LuoShenKui avatar Oct 02 '25 13:10 LuoShenKui

Is this a bad idea?

LuoShenKui avatar Oct 18 '25 07:10 LuoShenKui

Is this a bad idea?

I found this issue while searching for how to set the omitempty property for JSON tags in the global configuration.

yoon7t avatar Nov 20 '25 09:11 yoon7t