我有一个json示例,字段名称并不重要,但嵌套值和某些字段的数据类型是。据我所知,你必须确保在写csv时,使用csv.Writer时数据是字符串数据类型。我的问题是,编写嵌套值的正确方法是什么,是否有一种通过迭代整个json来转换所有非字符串值的有效方法?
`{
"name":"Name1",
"id": 2,
"jobs":{
"job1":"somejob",
"job2":"somejob2"
},
"prevIds":{
"id1": 100,
"id2": 102
}
}`
示例是json
答案 0 :(得分:4)
以下是一个工作示例:
package main
import (
"encoding/csv"
"encoding/json"
"fmt"
"log"
"os"
"strconv"
)
func decodeJson(m map[string]interface{}) []string {
values := make([]string, 0, len(m))
for _, v := range m {
switch vv := v.(type) {
case map[string]interface{}:
for _, value := range decodeJson(vv) {
values = append(values, value)
}
case string:
values = append(values, vv)
case float64:
values = append(values, strconv.FormatFloat(vv, 'f', -1, 64))
case []interface{}:
// Arrays aren't currently handled, since you haven't indicated that we should
// and it's non-trivial to do so.
case bool:
values = append(values, strconv.FormatBool(vv))
case nil:
values = append(values, "nil")
}
}
return values
}
func main() {
var d interface{}
err := json.Unmarshal(exampleJSON, &d)
if err != nil {
log.Fatal("Failed to unmarshal")
}
values := decodeJson(d.(map[string]interface{}))
fmt.Println(values)
f, err := os.Create("outputfile.csv")
if err != nil {
log.Fatal("Failed to create outputfile.csv")
}
defer f.Close()
w := csv.NewWriter(f)
if err := w.Write(values); err != nil {
log.Fatal("Failed to write to file")
}
w.Flush()
if err := w.Error(); err != nil {
log.Fatal("Failed to flush outputfile.csv")
}
}
var exampleJSON []byte = []byte(`{
"name":"Name1",
"id": 2,
"jobs":{
"job1":"somejob",
"job2":"somejob2"
},
"prevIds":{
"id1": 100,
"id2": 102
}
}`)
这可以通过解码任意JSON来实现,如this goblog post所示,然后通过以常规方式将其转换为字符串来迭代和处理每种可能的类型。如果您遇到map[string]interface{}
,那么您将重新获得下一组数据。
获得[]string
后,您可以将其传递给csv.Writer
,然后根据自己的喜好写出来。在这种情况下,输出是
Name1,2,somejob,somejob2,100,102