Golang实现JSON键值对追加与Map导出问题求助
解决Go中键值对JSON文件的读写与追加问题
要实现键值对形式的JSON文件({"key": value, ...}),核心是先读取现有数据合并,再覆盖写入,而不是直接追加字符串(这会导致JSON格式破坏,出现[{...}][{...}]这类无效结构)。以下是具体实现方案:
核心思路
JSON对象是单一的顶层结构,无法通过直接追加字符串来添加新键值对。正确流程是:
- 读取现有
db.json内容,若文件不存在则初始化空Map - 将JSON解析为Go的
map[string]interface{}(或特定类型Map) - 向Map中添加/更新键值对
- 将更新后的Map重新序列化为JSON,覆盖写入文件
完整代码实现
package main import ( "encoding/json" "os" ) // loadDB 读取db.json并解析为Map,文件不存在则返回空Map func loadDB(path string) (map[string]interface{}, error) { file, err := os.Open(path) if err != nil { if os.IsNotExist(err) { return make(map[string]interface{}), nil } return nil, err } defer file.Close() var db map[string]interface{} if err := json.NewDecoder(file).Decode(&db); err != nil { return nil, err } return db, nil } // saveDB 将Map序列化为JSON并写入db.json func saveDB(path string, db map[string]interface{}) error { // 创建文件(覆盖原有内容) file, err := os.Create(path) if err != nil { return err } defer file.Close() // 格式化输出JSON(可选,便于阅读) encoder := json.NewEncoder(file) encoder.SetIndent("", " ") return encoder.Encode(db) } // addKV 向db.json中添加/更新键值对 func addKV(path string, key string, value interface{}) error { db, err := loadDB(path) if err != nil { return err } db[key] = value return saveDB(path, db) } func main() { // 示例:添加两个键值对 if err := addKV("db.json", "username", "Arsh Ergon"); err != nil { panic(err) } if err := addKV("db.json", "role", "developer"); err != nil { panic(err) } }
关键说明
- 避免直接追加写入:直接用
os.O_APPEND模式写入JSON字符串会生成{"a":1}{"b":2}这类无效JSON,无法被正确解析为单个对象。 - 类型安全优化:如果你的值都是固定类型(比如全是字符串),可以将
map[string]interface{}替换为map[string]string,减少类型断言的麻烦。 - 原子写入(可选):如果需要避免写入失败导致文件损坏,可以先写入临时文件,再替换原文件:
func saveDB(path string, db map[string]interface{}) error { tempPath := path + ".tmp" file, err := os.Create(tempPath) if err != nil { return err } defer file.Close() encoder := json.NewEncoder(file) encoder.SetIndent("", " ") if err := encoder.Encode(db); err != nil { os.Remove(tempPath) return err } return os.Rename(tempPath, path) }
查询与导出Map
读取db.json后直接得到的就是Go的Map结构,可直接用于查询:
db, err := loadDB("db.json") if err != nil { panic(err) } // 查询键值 username := db["username"].(string)
内容的提问来源于stack exchange,提问作者Arsh Ergon
相关产品推荐
相关产品推荐

