英文:
SQLC - how to retrieve data stored as JSONB
问题
我有一个简单的表格,其中有一个字段是JSONB:
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的样板代码:
-- name: GetTestData :one
SELECT * FROM test_table
WHERE id = $1 LIMIT 1;
但是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的示例:
{
"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"
}
]
}
]
}
}
]
}
}
Static或Dynamic内部的嵌套属性是数组。
content属性应该包含一个嵌套对象,但我似乎无法提取其中的数据。json.Unmarshal()
似乎只能获取顶层属性。是否有一种方法可以将map[string]interface{}
转换为content,或者帮助SQLC将属性生成为接口而不是RawMessage?
我尝试解决这个问题,只需解组装载消息,如下所示:
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)
}
在解组装载数据时,我做错了什么,但我无法确定具体是什么。
这是一个示例 playground:go.dev/play/p/9e7a63hNMEA
英文:
I have a simple table that has a field JSONB:
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")
);
I used a simple query to generate boilerplate with SQLC.
-- name: GetTestData :one
SELECT * FROM test_table
WHERE id = $1 LIMIT 1;
But the content
property gets generated as 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"`
}
Here's a sample of the JSON that is stored inside the content column:
{
"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"
}
]
}
]
}
}
]
}
}
Nested properties inside Static or Dynamic are arrays.
The content property should contain a nested object, and I can't seem to extract the data inside it. json.Unrmarshall()
seems get only the top level properties. Is there a way to cast
map[string]interface{}
to content or to help SQLC generate the property as interface instead of RawMessage?
I tried to solve this just unmarshalling the raw message like so:
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)
}
I'm doing something wrong when unmarshalling the payload but I can't figure out what exactly.
Here's a sample playground: go.dev/play/p/9e7a63hNMEA
答案1
得分: 1
你的JSON包含static
和dynamic
键。你正在解析成map[string]json.RawMessage
,然后尝试从map中获取Static
和Dynamic
(注意大小写)。
修复map的键(例如json.Unmarshal(res["static"], &static)
),你的代码可能会正常工作。一个更好的解决方案可能是在尝试解析之前检查键是否存在。
英文:
Your JSON contains static
and dynamic
keys. You are parsing into a map[string]json.RawMessage
and then trying to retrieve Static
and Dynamic
from the map (note the capitalisation).
Fix the map keys (i.e. json.Unmarshal(res["static"], &static)
)and your code will probably work. A better solution might be to check if the keys exist before attempting to unmarshal them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论