You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLC检索JSONB存储数据遇阻:嵌套JSON解析及类型生成问题

JSONB字段解析与SQLC类型生成问题

表结构定义

我有一个包含JSONB类型字段的PostgreSQL表,结构如下:

CREATE TABLE IF NOT EXISTS "test_table" (
    "id" text NOT NULL,
    "user_id" text NOT NULL,
    "content" jsonb NOT NULL,
    "create_time" timestamptz NOT NULL,
    "update_time" timestamptz NOT NULL,
    PRIMARY KEY ("id")
);

SQLC代码生成情况

我用SQLC执行如下查询生成Go代码:

-- name: GetTestData :one
SELECT * FROM test_table
WHERE id = $1 LIMIT 1;

生成的TestTable结构体中,Content字段被定义为json.RawMessage:

type TestTable struct {
    ID          string          `json:"id"`
    UserId      string          `json:"user_id"`
    Content     json.RawMessage `json:"content"`
    CreateTime  time.Time       `json:"create_time"`
    UpdateTime  time.Time       `json:"update_time"`
}

Content字段的JSON示例

content列存储的JSON结构如下:

{
  "static": {
    "product": [
      {
        "id": "string",
        "elements": {
          "texts": [
            {
              "id": "string",
              "value": "string"
            }
          ],
          "colors": [
            {
              "id": "string",
              "value": "string"
            }
          ],
          "images": [
            {
              "id": "string",
              "values": [
                {
                  "id": "string",
                  "value": "string"
                }
              ]
            }
          ]
        }
      }
    ]
  },
  "dynamic": {
    "banner": [
      {
        "id": "string",
        "elements": {
          "texts": [
            {
              "id": "string",
              "value": "string"
            }
          ],
          "colors": [
            {
              "id": "string",
              "value": "string"
            }
          ],
          "images": [
            {
              "id": "string",
              "values": [
                {
                  "id": "string",
                  "value": "string"
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

解析失败的尝试

我尝试解析Content字段但未能成功,代码如下:

var res map[string]json.RawMessage
if err := json.Unmarshal(testingData.Content, &res); err != nil {
    return nil, status.Errorf(codes.Internal, "Serving data err %s", err)
}

var static pb.Static
if err := json.Unmarshal(res["Static"], &static); err != nil {
    return nil, status.Errorf(codes.Internal, "Static data err %s", err)
}
var dynamic pb.Dynamic
if err := json.Unmarshal(res["Dynamic"], &dynamic); err != nil {
    return nil, status.Errorf(codes.Internal, "Dynamic data err %s", err)
}

解决方案

1. 修复解析代码的错误

解析失败的核心原因是JSON键名大小写不匹配:JSON中的键是小写的static和dynamic,但代码中用了大写开头的res["Static"]、res["Dynamic"],导致无法找到对应数据。

修正后的代码:

var res map[string]json.RawMessage
if err := json.Unmarshal(testingData.Content, &res); err != nil {
    return nil, status.Errorf(codes.Internal, "解析数据失败: %s", err)
}

var static pb.Static
if err := json.Unmarshal(res["static"], &static); err != nil {
    return nil, status.Errorf(codes.Internal, "解析Static数据失败: %s", err)
}

var dynamic pb.Dynamic
if err := json.Unmarshal(res["dynamic"], &dynamic); err != nil {
    return nil, status.Errorf(codes.Internal, "解析Dynamic数据失败: %s", err)
}

同时需要确保pb.Static和pb.Dynamic结构体的JSON标签与JSON结构完全匹配(比如Static结构体的product字段要有json:"product"标签)。

2. 让SQLC直接生成自定义类型

通过SQLC的配置文件,可以指定JSONB字段对应的Go类型,避免手动Unmarshal操作:

  1. 在项目根目录创建sqlc.yaml配置文件,添加类型映射规则:
version: "2"
sql:
  - schema: "schema.sql"
    queries: "queries.sql"
    engine: "postgresql"
    gen:
      go:
        package: "db"
        out: "db"
        overrides:
          - db_type: "jsonb"
            go_type: "yourpackage.ContentStruct" # 替换为你的自定义结构体路径
            # 若需直接映射为map类型,可改为:
            # go_type: "map[string]interface{}"
  1. 定义与JSON结构匹配的自定义结构体(示例):
package yourpackage

type ContentStruct struct {
    Static  StaticContent  `json:"static"`
    Dynamic DynamicContent `json:"dynamic"`
}

type StaticContent struct {
    Product []Product `json:"product"`
}

type DynamicContent struct {
    Banner []Product `json:"banner"`
}

type Product struct {
    ID       string   `json:"id"`
    Elements Elements `json:"elements"`
}

type Elements struct {
    Texts  []Text  `json:"texts"`
    Colors []Color `json:"colors"`
    Images []Image `json:"images"`
}

type Text struct {
    ID    string `json:"id"`
    Value string `json:"value"`
}

type Color struct {
    ID    string `json:"id"`
    Value string `json:"value"`
}

type Image struct {
    ID     string       `json:"id"`
    Values []ImageValue `json:"values"`
}

type ImageValue struct {
    ID    string `json:"id"`
    Value string `json:"value"`
}

重新运行SQLC生成代码后,TestTable的Content字段会直接是你定义的ContentStruct类型,无需手动解析。


内容的提问来源于stack exchange,提问作者Mido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:00:58