JSON将数字视为base64 golang

JSON将数字视为base64 golang,json,go,Json,Go,试图将查询输出作为JSON发送到浏览器,但数字被视为Base64。整数输出正确 var rows *sqlx.Rows enc := json.NewEncoder(w) rows, err = db.Queryx(query) for rows.Next() { results := make(map[string]interface{}) err = rows.MapScan(results) if err := enc.Encode(results);

试图将查询输出作为JSON发送到浏览器,但数字被视为Base64。整数输出正确

 var rows *sqlx.Rows 
 enc := json.NewEncoder(w)

 rows, err = db.Queryx(query)
  for rows.Next() {
    results := make(map[string]interface{})
    err = rows.MapScan(results)
    if err := enc.Encode(results); err != nil{
       fmt.Fprintf(w,"%s\n", results)
    }
 }
JSON的结果是(id integer、数量数字/浮动):

{“ID”:1,“数量”:“OC4wMA==”}

{“ID”:2,“数量”:“OC4wMA==”}

如果没有JSON编码,数字列被视为正确的数字

编辑

@mkopriva希望这个答案有助于:

“如果您提供表定义以便我们可以看到列是如何定义的,那么查看SQL查询也会有所帮助,以便我们可以看到您是如何从数据库中提取列的”

如果您提供您提到的“将列正确视为数字”的代码及其输出,也会有所帮助。

给出以下结果:

地图[ID:1数量:9.75]

地图[ID:2数量:7.00]

“您能为我们执行fmt.Printf(“%T”,results[“QTY”])吗?如果“QTY”真的是int或float,json编码器会将其封送为base64字符串,这是非常值得怀疑的。

如果没有JSON,这将提供:

[]uint8 []uint8


假设您使用的是
lib/pq
quantity
值被转换成一个字节片,该字节片实际上是对应postgres
numeric
类型的正确类型。这是因为
numeric
类型的值不能可靠地适合
float64
而不降低精度,因此它会导致驱动程序选择将postgres
数值
值转换为Go
[]字节

请看这里:

但是,您可以通过将类型为
*float64
的Go值传递给
Scan
方法系列,明确地告诉驱动程序您需要一个float,并且驱动程序会将
数值
转换为
float64
,在这个过程中会丢失精度。但是如果传递
接口{}
,驱动程序将做出最合适的选择,并将值转换为字节片

如果您不关心精度,但必须使用
接口{}
作为
扫描
的参数,则可以将表列的类型从
数值
更改为
浮点
,如果这样做,则驱动程序可以安全地选择将列转换为Go
浮点64

如果您关心精度,但出于某种原因必须使用接口映射,则可以编写一个简单的函数,将映射中已知键的值从
[]转换为字节
到字符串,之后,当您将更新后的映射传递给json编码器时,您将看到该键的值被编码为普通字符串,而不是base64

func bytesToString(k string, m map[string]interface{}) {
    if b, ok := m[k].([]byte); ok {
        m[k] = string(b)
    }
}

假设您使用的是
lib/pq
quaty
值被转换为字节片,该字节片实际上是对应postgres
numeric
类型的正确类型。这是因为
numeric
类型的值不能可靠地适合
float64
而不降低精度,因此驱动程序选择将postgres
数值
值转换为Go
[]字节
值是有意义的

请看这里:

但是,您可以通过将类型为
*float64
的Go值传递给
Scan
方法系列,明确地告诉驱动程序您需要一个float,并且驱动程序会将
数值
转换为
float64
,在这个过程中会丢失精度。但是如果传递
接口{}
,驱动程序将做出最合适的选择,并将值转换为字节片

如果您不关心精度,但必须使用
接口{}
作为
扫描
的参数,则可以将表列的类型从
数值
更改为
浮点
,如果这样做,则驱动程序可以安全地选择将列转换为Go
浮点64

如果您关心精度,但出于某种原因必须使用接口映射,则可以编写一个简单的函数,将映射中已知键的值从
[]转换为字节
到字符串,之后,当您将更新后的映射传递给json编码器时,您将看到该键的值被编码为普通字符串,而不是base64

func bytesToString(k string, m map[string]interface{}) {
    if b, ok := m[k].([]byte); ok {
        m[k] = string(b)
    }
}

经过无数次尝试,我找到了一个解决方案,通过将数字转换为字符串来解决问题。这并不理想,但相当简单

var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))

for i, _ := range cols {  //bytes to string
   vals[i] = &cols[i]
}

mymap := make(map[string]interface{})

for i, v := range vals {  //adding column names
  mymap[colnames[i]] = v
}

for rows.Next() {
   err = rows.Scan(vals...)
   json, _ := json.Marshal(mymap)
   fmt.Fprintf(w,"%s\n",json)
}

请随意投反对票,但请允许我解释原因。

经过无数次尝试,我找到了一个解决方案,通过将数字转换为字符串来解决问题。这并不理想,但相当简单

var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))

for i, _ := range cols {  //bytes to string
   vals[i] = &cols[i]
}

mymap := make(map[string]interface{})

for i, v := range vals {  //adding column names
  mymap[colnames[i]] = v
}

for rows.Next() {
   err = rows.Scan(vals...)
   json, _ := json.Marshal(mymap)
   fmt.Fprintf(w,"%s\n",json)
}

请随意向下投票,但请允许我解释原因。

如果您已经知道返回结果的结构,那么为什么不使用struct,然后将其发送给browserI?我不知道该结构。从表中选择*。这意味着您的DB驱动程序返回的不是数字,而是字节片,
[]字节
,这就是它们被封送为JSON base64编码的原因。您必须找出这些列的实际DB数据类型,这些列包含您认为是数字的内容,然后问一个更全面的问题,以便我们能够有根据地猜测数据库类型与Go类型之间的不匹配情况。@kostix It在Postgresql中存储为数字,在不使用JSON时显示为数字。因此,它可能是Postgresql驱动程序?告诉您哪些类型被视为
[]字节
。如果您已经知道返回结果的结构,那么为什么不使用struct,然后将其发送到browserI?我不知道该结构。请从表中选择*。这意味着您的DB驱动程序返回的不是数字,而是字节片,
[]字节
,这就是它们被封送为JSON base64编码的原因。您必须找出这些列的实际DB数据类型,这些列包含您认为是数字的内容,然后问一个更全面的问题,以便我们能够