• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    在golang xorm中使用postgresql的json,array类型的操作

    xorm支持各种关系数据库,最近使用postgresql时,总是踩到一些坑,在此记录下解决方式。

    在使用postgresql的array类型时,查询有点问题,xorm的官方文档给出重写的方式,但是不是很清晰:

    官方文档链接:http://xorm.io/docs

    也就是说碰到基础库不支持的类型,需要我们去重写ToDB、FromDB方法,废话不多说直接上代码:

    比如int8[]类型,自定一个Int64Array

    type Int64Array []int64
    
    func (s *Int64Array) FromDB(bts []byte) error {
    	if len(bts) == 0 {
    		return nil
    	}
    
    	str := string(bts)
    	if strings.HasPrefix(str, "{") {
    		str = "[" + str[1:len(str)]
    	}
    
    	if strings.HasSuffix(str, "}") {
    		str = str[0: len(str)-1] + "]"
    	}
    
    	var ia = []int64{}
    
    	err := json.Unmarshal([]byte(str), ia)
    	if err != nil {
    		return err
    	}
    
    	*s = Int64Array(*ia)
    	return nil
    }
    
    func (s *Int64Array) ToDB() ([]byte, error) {
    	return serializeBigIntArray(*s, "{", "}"), nil
    }
    
    func (arr Int64Array) MarshalJSON() ([]byte, error) {
    	return serializeBigIntArrayAsString(arr, "[", "]"), nil
    }
    
    func (arr *Int64Array) UnmarshalJSON(b []byte) error {
    	var strarr []string
    	var intarr []int64
    
    	err := json.Unmarshal(b, strarr)
    	if err != nil {
    		return err
    	}
    
    	for _, s := range strarr {
    		i, err := strconv.ParseInt(s, 10, 64)
    		if err != nil {
    			return err
    		}
    
    		intarr = append(intarr, i)
    	}
    
    	*arr = intarr
    	return nil
    }
    
    func serializeBigIntArray(s []int64, prefix string, suffix string) []byte {
    	var buffer bytes.Buffer
    
    	buffer.WriteString(prefix)
    
    	for idx, val := range s {
    		if idx > 0 {
    			buffer.WriteString(",")
    		}
    		buffer.WriteString(strconv.FormatInt(val, 10))
    	}
    
    	buffer.WriteString(suffix)
    
    	return buffer.Bytes()
    }
    
    func serializeBigIntArrayAsString(s []int64, prefix string, suffix string) []byte {
    	var buffer bytes.Buffer
    
    	buffer.WriteString(prefix)
    
    	for idx, val := range s {
    		if idx > 0 {
    			buffer.WriteString(",")
    		}
    		buffer.WriteString("\"")
    		buffer.WriteString(strconv.FormatInt(val, 10))
    		buffer.WriteString("\"")
    	}
    	buffer.WriteString(suffix)
    	return buffer.Bytes()
    }

    json类型:

    type Cover struct {
     Id   int64  `json:"id,omitempty"`
     Fid  string `json:"fid,omitempty"`
     Type int8   `json:"type,omitempty"`
     Url  string `json:"url,omitempty"`
    }
    
    func (c *Cover) FromDB(bytes []byte) error {
     return json.Unmarshal(bytes, c)
    }
    
    func (c *Cover) ToDB() (bytes []byte, err error) {
     bytes, err = json.Marshal(c)
     return
    }
    

    具体使用:

    type Course struct {
    	Id            int64             `json:"id,string" form:"id"`
    	Name          string            `json:"name" form:"name"`
    	Brief         string            `json:"brief" form:"brief"`
    	Description   string            `json:"description" form:"description"`
    	Cover         common.Cover      `xorm:"Text" json:"cover" form:"cover"`
    	Categories    common.Int64Array `xorm:"Text" json:"categories" form:"categories[]"`
    	Tags          common.Int64Array `json:"tags" form:"tags[]"`
    	Difficulty    float64           `json:"difficulty" form:"difficulty"`
    	Price         float64           `json:"price" form:"price"`
    	Markets       common.Int64Array `json:"markets" form:"markets[]"`
    	StudentAmount int64             `json:"studentAmount" form:"studentAmount"`
    	SubjectAmount int64             `json:"subjectAmount" form:"subjectAmount"`
    	Crt           time.Time         `json:"crt"`
    	Lut           time.Time         `json:"lut"`
    	Status        int16             `json:"status" form:"status"`
    	common.Page                     `xorm:"-"`
    }

    补充:golang gin xorm注意事项

    1. 无论是golang还是xorm中,在填写j'son字段时,注意空格,比如 `json:"abcd "` `json:"abcd"`是不一样的,不仔细对比会出错

    2.当结合gin框中的

    c.JSON(http.StatusOK,gin.H{})操作

    并且使用xorm中的join,find操作时(https://www.kancloud.cn/xormplus/xorm/167102)要注意如下现象,

    假如定义两个结构体对应两个表

    然后使用联合查询,先把两个结构体结合成一个结构体,假如如下,在UserGroup中使用User和Group匿名结构体,

    那么当我们使用gin的c.JSON(http.StatusOK,gin.H{"data":UserGroup})返回数据时会导致Group和User中同名字段显示不了,这应该是gin和xorm的不是很兼容造成的(没有深究),

    要解决这个问题,最好让UserGroup中的User和Group不要以匿名结构体的形式存在

    可以改成

    type UserGroup struct {
        MyUser  User `xorm:"extends" json:"你要json中返回的名字"`
        MyGroup Group `xorm:"extends" json:"你要json中返回的名字"`
    }

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • golang xorm及time.Time自定义解决json日期格式的问题
    • golang xorm日志写入文件中的操作
    • go语言 xorm框架 postgresql 的用法及详细注解
    • golang中xorm的基本使用说明
    • 解决goxorm无法更新值为默认值的问题
    • xorm根据数据库生成go model文件的操作
    • 使用go xorm来操作mysql的方法实例
    • go xorm框架的使用
    上一篇:解决golang时间字符串转time.Time的坑
    下一篇:golang 阻止主goroutine退出的操作
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    在golang xorm中使用postgresql的json,array类型的操作 在,golang,xorm,中,使用,postgresql,