sql: 列索引 5 上的扫描错误,名称“todos”:不支持扫描,将 driver.Value 类型 []uint8 存储到类型 *[]datatypes.JSON golang gorm

分享于2022年07月17日 arrays database go go-gorm json 问答
【问题标题】:sql: 列索引 5 上的扫描错误,名称“todos”:不支持扫描,将 driver.Value 类型 []uint8 存储到类型 *[]datatypes.JSON golang gorm(sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm)
【发布时间】:2022-01-15 22:09:56
【问题描述】:

这是模型:

type Board struct {
    Id     uint `gorm:"primaryKey;autoIncrement;unique" json:"id"`
    Owner  uint `json:"owner"`
    Name string `json:"name"`
    Contributors []int `gorm:"type:jsonb" json:"contributors"`
    GeneratedLink string `gorm:"default:''" json:"generated_link"`
    Todos []datatypes.JSON `gorm:"type:jsonb" json:"todos"`
}

type TodoStructure struct {
    Id string `json:"id"`
    Text string `json:"text"`
    Completed bool `json:"completed"`
    Important bool `json:"important"`
}

这就是我创建董事会的方式:

board := models.Board{
    Owner:         20,
    Name:          "text",
    GeneratedLink: "",
    Todos: []datatypes.JSON{datatypes.JSON("[]")},
}

database.DB.Create(&board)

这是创建板后列的外观: sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm

所以 todos 只是一个空数组。这就是我创建待办事项的方式:

func createTodo(c *gin.Context) {
    var board models.board
    database.DB.Where("id = ?", 1).First(&board)
    id := uuid.NewV4().String()
    todoStruct := models.TodoStructure{
        Id:        id,
        Text:      "text",
        Completed: false,
        Important: false,
    }

    jsonData, _ := json.Marshal(todoStruct)
    board.Todos = append(board.Todos, jsonData)
    fmt.Println(board.Todos) //exactly what i need [{"id":"e7ee015ab54c48388aa2413428f76f50","text":"text","completed":false,"important":false}]
    database.DB.Save(&board)
    c.JSON(http.StatusCreated, gin.H{"message": "success"})
}

但我得到了错误:

sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON

并且在列中的 todo 值保存如下:

sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm

sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm

只是 json 对象,但我需要像这样保存:

[{"id":"e7ee015ab54c48388aa2413428f76f50","text":"text","completed":false,"important":false}]

sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm

sql: Scan error on column index 5, name "todos": unsupported Scan, storing driver.Value type []uint8 into type *[]datatypes.JSON golang gorm

请任何想法,任何选项,我试图在谷歌中找到解决方案,但没有找到正确的解决方案。

P.S 使用 gorm 和 postgresql

  • 对于 type:jsonb 使用 datatypes.JSON 。即删除 [] datatypes.JSON 类型 可以 表示任何有效的 JSON,包括 JSON 数组,即用于存储 [{"id":"123",...}] 是合适的。另一方面, []datatypes.JSON 类型表示 JSON 类型的 discrete 元素的切片,因为您需要在 postgresql 中使用 jsonb[] (即 jsonb 数组)。
  • @mkopriva 在模型中我删除了 [] 现在它只是 datatypes.JSON 但现在在创建 todo 函数中我得到了错误: Cannot use 'jsonData' (type []byte) as the type byte screenshot of an error
  • 删除附加: board.Todos = jsonData
  • @mkopriva 它再次保存为 json 对象,而不是这样: [{"id":"e7ee015ab54c48388aa2413428f76f50","text":"text","completed":false,"important":false}]
  • 如果您“确切需要”的是 JSON 中的 对象数组 ,即 [{"id": ... ,而不仅仅是一个对象,即 {"id": ... ,那么你应该 json.Marshal 一个切片而不是一个单一的结构。即你可以这样做: json.Marshal([]models.TodoStructure{todoStruct}) .

【解决方案1】:

我认为您使用了不正确的数据类型。你可以试试这条线吗?

    Todos []byte `gorm:"type:jsonb" json:"todos"`