当前位置: 首页 > 工具软件 > Argo JSON > 使用案例 >

Go 数据库存储数组、json类型

张嘉
2023-12-01

本文主要介绍用数据库varchar字段存储序列化数据。
通过实现 database/sql/driver 的接口,实现Value() (driver.Value, error)Scan(interface{}) error函数。

一、数组(demo为int,string同理)

package xx
import (
   "database/sql/driver"
   "encoding/json"
)

type IntArray []int

// 入库。实现 driver.Valuer 接口,Value 返回 json value
func (j IntArray) Value() (driver.Value, error) {
   if len(j) == 0 {
   	return "", nil
   }

   bytes, err := json.Marshal(j)
   if err != nil {
   	return "", nil
   }

   return string(bytes), nil
}

// 出库。实现 sql.Scanner 接口,Scan 将 value 扫描至 Jsonb
func (j *IntArray) Scan(value interface{}) error {
   bytes, ok := value.([]byte)
   if !ok || len(bytes) == 0 {
   	return nil
   }

   result := IntArray{}
   err := json.Unmarshal(bytes, &result)
   *j = IntArray(result)
   return err
}



二、Json

有个需求。根据类型字段typecontent存储不同的结构体。 拿出来的时候对外暴露不同的结构体对象。隐藏content
我一开始的做法是把content声明为string, 然后拿出来的时候解析到不同的结构体。 倒也没啥毛病。但是总觉得别扭,要先转为[]byte再判断解析。

package xx
import (
	"database/sql/driver"
	"encoding/json"
)

type Json []byte

// 入库,自动调用
func (j Json) Value() (driver.Value, error) {
	if len(j) <= 4 {
		return "", nil
	}
	return string(j), nil
}

// 出库,自动调用
func (j *Json) Scan(value interface{}) error {
	bytes, _ := value.([]byte)
	if len(bytes) > 4 {
		*j = Json(bytes)
	}
	return nil
}

// 解析到,手动调用
func (j Json) ParseAs(to interface{}) (err error) {
	if len(j) > 0 {
		err = json.Unmarshal([]byte(j), to)
		if err != nil {
			log.Println("ERROR JSON 解析错误", err)
		}
	}
	return
}

三、布尔

布尔适用于数据库用tinyint存储两种状态。 我们默认1为true,0为false

type Boolean bool

func (b Boolean) Value() (driver.Value, error) {
	var v int64
	if b {
		v = 1
	}
	return v, nil
}

func (b *Boolean) Scan(value interface{}) (err error) {
	*b = (value.(int64) != 0)
	return
}
 类似资料: