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
CodePudding user response:
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.