如何从MySQL中获取具有正确字段类型的JSON数据?

huangapple go评论75阅读模式
英文:

How to get JSON data from MySQL with correct field type?

问题

我是一个初学者,正在学习Golang。我阅读了很多关于从MySQL数据库获取JSON的线程,但还有一个问题没有得到解答:JSON中所有字段的值都是字符串,而不是它们正确的类型,无论是整数还是时间。

我正在使用的代码如下:

var emptyOut []byte
rows, err := db.Query(sqlString)
if err != nil {
    return emptyOut, err
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
    return emptyOut, err
}
count := len(columns)
tableData := make([]map[string]interface{}, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
    for i := 0; i < count; i++ {
        valuePtrs[i] = &values[i]
    }
    rows.Scan(valuePtrs...)
    entry := make(map[string]interface{})
    for i, col := range columns {
        var v interface{}
        val := values[i]
        b, ok := val.([]byte)
        if ok {
            v = string(b)
        } else {
            v = val
        }
        entry[col] = v
    }
    tableData = append(tableData, entry)
}
jsonData, err := json.Marshal(tableData)
if err != nil {
    return emptyOut, err
}
return jsonData, nil

将数据转换为字符串的部分肯定是这一段:

v = string(b)

所以问题是:如何将v转换为正确的b值类型。这将节省我在以后处理错误字段类型时的大量工作。提前谢谢!

英文:

I am a beginner to Golang. I've read many threads about getting JSON from a mysql database, but there is a question left unanswered: the values of all fields in the JSON are strings and not their correct types, be it integer or time.

The code I'm using:

var emptyOut []byte
rows, err := db.Query(sqlString)
if err != nil {
	return emptyOut, err
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
	return emptyOut, err
}
count := len(columns)
tableData := make([]map[string]interface{}, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
	for i := 0; i &lt; count; i++ {
		valuePtrs[i] = &amp;values[i]
	}
	rows.Scan(valuePtrs...)
	entry := make(map[string]interface{})
	for i, col := range columns {
		var v interface{}
		val := values[i]
		b, ok := val.([]byte)
		if ok {
			v = string(b)
		} else {
			v = val
		}
		entry[col] = v
	}
	tableData = append(tableData, entry)
}
jsonData, err := json.Marshal(tableData)
if err != nil {
	return emptyOut, err
}
return jsonData, nil

The part that turns data into string is surely this one:

v = string(b)

So the question is: how to turn v into the right type of value of b. This will save a lot of my effort in dealin with wrong field type later on. Thank you in advance!

答案1

得分: 1

我对你的问题的限制条件还有一些不太清楚。

如果你事先知道数据库的模式,我建议创建一个表示数据的结构体。然后你可以使用数据库库gorm将数据获取到一个结构体切片中。你可以给结构体添加go tags,并将结构体切片转换为JSON,其中字段被正确地编组为它们的正确类型。
例如(未经测试):

type MyDataSchema struct {
    Id         int    `json:"id"`
    Name       string `json:"name"`
    Birth      time.Time `json:"birth_date,omitempty"`
}
...
rows := &[]MyDataSchema{}
result := db.Find(&rows)
b, err := json.Marshal(result)

如果你事先不知道模式,那就有点棘手了。在Go语言中有一种叫做type switch的东西,你可能需要考虑使用它:
如果我正确理解你的代码,val := values[i]中的val是一个接口类型。所以你可以这样做(未经测试):

    switch v := i.(type) {
    case int:
        entry[col] = v
    case string:
        entry[col] = v
    case time.Time:
        entry[col] = v
    //你可以添加更多的类型
    default:
        entry[col] = val
    }

这可能不是一个完整的答案,但希望能帮助你解决问题。

英文:

I am a little unclear on the constraints of your problem.

If you know the database schema before hand, I would create a struct that represents your data. You can then use the database library gorm to get the data into a struct slice. You can add go tags to the struct and convert the struct slice to json with the fields marshaled into their correct types.
For example (untested):


type MyDataSchema struct {
    Id         int    `json:&quot;id&quot;`
    Name       string `json:&quot;name&quot;`
    Birth time.Time `json:&quot;birth_date,omitempty&quot;`
}
...
rows:=&amp;DataSchema{}
result := db.Find(&amp;rows)
b, err := json.Marshal(result)


If you dont know the schema before hand, then it is a little bit more tricky. In go there is such a thing as a type switch. You might want to consider that:
If I am following your code correctly, val := values[i] val is of type interface. So you could do something like (untested):

	switch v := i.(type) {
	case int:
		entry[col]=v
	case string:
		entry[col]=v
    case time.Time:	
        entry[col]=v
//you can add more types
    default:
		entry[col]=val
	}

This might not be a complete answer but hopefully it gets you to where you need.

huangapple
  • 本文由 发表于 2022年6月24日 12:32:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/72739033.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定