Ric*_*nia 7 serialization json go
我有一个使用字符串作为键和值的映射.我有一个键数组,指定映射值的顺序.
我想将该映射序列化为JSON,但保持在数组上定义的顺序.
这里有一个示例代码:http://play.golang.org/p/A52GTDY6Wx
我想将它序列化为:
{
"name": "John",
"age": "20"
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我直接序列化地图,则按字母顺序排列键:
{
"age": "20",
"name": "John"
}
Run Code Online (Sandbox Code Playgroud)
我可以将它序列化为一个映射数组,从而保持顺序,但是会产生许多不需要的字符:
[
{
"name": "John"
},
{
"age": "20"
}
]
Run Code Online (Sandbox Code Playgroud)
在我的实际代码中,我需要序列化在文本文件中指定的数据库查询的结果,并且我需要维护列顺序.我不能使用结构,因为在编译时不知道列.
编辑:我不需要按照指定的顺序读取JSON.生成的JSON应该由人们阅读,所以我只是希望它尽可能具有人类可读性.
我可以使用自定义格式,但JSON非常适合我.
谢谢!
eri*_*ang 11
您需要json.Marshaler在自定义类型上实现该接口.这具有在其他结构类型中良好运行的优点.
对不起,您总是需要编写一些JSON编码代码.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
type KeyVal struct {
Key string
Val interface{}
}
// Define an ordered map
type OrderedMap []KeyVal
// Implement the json.Marshaler interface
func (omap OrderedMap) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
buf.WriteString("{")
for i, kv := range omap {
if i != 0 {
buf.WriteString(",")
}
// marshal key
key, err := json.Marshal(kv.Key)
if err != nil {
return nil, err
}
buf.Write(key)
buf.WriteString(":")
// marshal value
val, err := json.Marshal(kv.Val)
if err != nil {
return nil, err
}
buf.Write(val)
}
buf.WriteString("}")
return buf.Bytes(), nil
}
func main() {
dict := map[string]interface{}{
"orderedMap": OrderedMap{
{"name", "John"},
{"age", 20},
},
}
dump, err := json.Marshal(dict)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", dump)
}
Run Code Online (Sandbox Code Playgroud)
输出
{"orderedMap":{"name":"John","age":20}}
Run Code Online (Sandbox Code Playgroud)
对于该特定要求,您实际上根本不需要使用json.Marshal,您可以简单地实现自己的函数,如下所示:
type OrderedMap map[string]string
func (om OrderedMap) ToJson(order ...string) string {
buf := &bytes.Buffer{}
buf.Write([]byte{'{', '\n'})
l := len(order)
for i, k := range order {
fmt.Fprintf(buf, "\t\"%s\": \"%v\"", k, om[k])
if i < l-1 {
buf.WriteByte(',')
}
buf.WriteByte('\n')
}
buf.Write([]byte{'}', '\n'})
return buf.String()
}
func main() {
om := OrderedMap{
"age": "20",
"name": "John",
}
fmt.Println(om.ToJson("name", "age"))
}
Run Code Online (Sandbox Code Playgroud)