使用结构字段(而不是 JSON 键)将结构体写入 JSON 文件

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

Write Struct to Json File using Struct Fields (not json keys)

问题

如何将一个json文件读入一个结构体中,然后将其重新编组为一个json字符串,其中结构体字段作为键(而不是原始的json键)?

(请参见下面的“期望的输出到Json文件”...)

代码:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. )
  7. type Rankings struct {
  8. Keyword string `json:"keyword"`
  9. GetCount uint32 `json:"get_count"`
  10. Engine string `json:"engine"`
  11. Locale string `json:"locale"`
  12. Mobile bool `json:"mobile"`
  13. }
  14. func main() {
  15. var jsonBlob = []byte(`
  16. {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
  17. `)
  18. rankings := Rankings{}
  19. err := json.Unmarshal(jsonBlob, &rankings)
  20. if err != nil {
  21. // nozzle.printError("opening config file", err.Error())
  22. }
  23. rankingsJson, _ := json.Marshal(rankings)
  24. err = ioutil.WriteFile("output.json", rankingsJson, 0644)
  25. fmt.Printf("%+v", rankings)
  26. }

屏幕上的输出:

  1. {Keyword:hipaa compliance form GetCount:157 Engine:google Locale:en-us Mobile:false}

输出到Json文件:

  1. {"keyword":"hipaa compliance form","get_count":157,"engine":"google","locale":"en-us","mobile":false}

期望的输出到Json文件:

  1. {"Keyword":"hipaa compliance form","GetCount":157,"Engine":"google","Locale":"en-us","Mobile":false}
英文:

How can I read a json file into a struct, and then Marshal it back out to a json string with the Struct fields as keys (rather than the original json keys)?

(see Desired Output to Json File below...)

Code:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. )
  7. type Rankings struct {
  8. Keyword string `json:"keyword"`
  9. GetCount uint32 `json:"get_count"`
  10. Engine string `json:"engine"`
  11. Locale string `json:"locale"`
  12. Mobile bool `json:"mobile"`
  13. }
  14. func main() {
  15. var jsonBlob = []byte(`
  16. {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
  17. `)
  18. rankings := Rankings{}
  19. err := json.Unmarshal(jsonBlob, &rankings)
  20. if err != nil {
  21. // nozzle.printError("opening config file", err.Error())
  22. }
  23. rankingsJson, _ := json.Marshal(rankings)
  24. err = ioutil.WriteFile("output.json", rankingsJson, 0644)
  25. fmt.Printf("%+v", rankings)
  26. }

Output on screen:

  1. {Keyword:hipaa compliance form GetCount:157 Engine:google Locale:en-us Mobile:false}

Output to Json File:

  1. {"keyword":"hipaa compliance form","get_count":157,"engine":"google","locale":"en-us","mobile":false}

Desired Output to Json File:

  1. {"Keyword":"hipaa compliance form","GetCount":157,"Engine":"google","Locale":"en-us","Mobile":false}

答案1

得分: 30

如果我正确理解你的问题,你只想从结构定义中删除json标签。

所以:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. )
  7. type Rankings struct {
  8. Keyword string
  9. GetCount uint32
  10. Engine string
  11. Locale string
  12. Mobile bool
  13. }
  14. func main() {
  15. var jsonBlob = []byte(`
  16. {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
  17. `)
  18. rankings := Rankings{}
  19. err := json.Unmarshal(jsonBlob, &rankings)
  20. if err != nil {
  21. // nozzle.printError("opening config file", err.Error())
  22. }
  23. rankingsJson, _ := json.Marshal(rankings)
  24. err = ioutil.WriteFile("output.json", rankingsJson, 0644)
  25. fmt.Printf("%+v", rankings)
  26. }

结果为:

  1. {Keyword:hipaa compliance form GetCount:0 Engine:google Locale:en-us Mobile:false}

输出文件为:

  1. {"Keyword":"hipaa compliance form","GetCount":0,"Engine":"google","Locale":"en-us","Mobile":false}

在http://play.golang.org/p/dC3s37HxvZ上运行示例。

注意:GetCount显示为0,因为它被读取为"get_count"。如果你想读取具有"get_count"而输出"GetCount"的JSON,那么你需要进行一些额外的解析。

有关此特定情况的其他信息,请参见https://stackoverflow.com/q/11527935/1162491。

英文:

If I understand your question correctly, all you want to do is remove the json tags from your struct definition.

So:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. )
  7. type Rankings struct {
  8. Keyword string
  9. GetCount uint32
  10. Engine string
  11. Locale string
  12. Mobile bool
  13. }
  14. func main() {
  15. var jsonBlob = []byte(`
  16. {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
  17. `)
  18. rankings := Rankings{}
  19. err := json.Unmarshal(jsonBlob, &rankings)
  20. if err != nil {
  21. // nozzle.printError("opening config file", err.Error())
  22. }
  23. rankingsJson, _ := json.Marshal(rankings)
  24. err = ioutil.WriteFile("output.json", rankingsJson, 0644)
  25. fmt.Printf("%+v", rankings)
  26. }

Results in:

  1. {Keyword:hipaa compliance form GetCount:0 Engine:google Locale:en-us Mobile:false}

And the file output is:

  1. {"Keyword":"hipaa compliance form","GetCount":0,"Engine":"google","Locale":" en-us","Mobile":false}

Running example at http://play.golang.org/p/dC3s37HxvZ

Note: GetCount shows 0, since it was read in as "get_count". If you want to read in JSON that has "get_count" vs. "GetCount", but output "GetCount" then you'll have to do some additional parsing.

See https://stackoverflow.com/q/11527935/1162491 for additional info about this particular situation.

答案2

得分: 1

尝试在结构体中更改JSON格式:

  1. type Rankings struct {
  2. Keyword string `json:"关键词"`
  3. GetCount uint32 `json:"获取次数"`
  4. Engine string `json:"引擎"`
  5. Locale string `json:"区域"`
  6. Mobile bool `json:"移动设备"`
  7. }

请注意,我将JSON标签翻译为中文,以便更符合中文语境。

英文:

Try to change the json format in the struct

  1. type Rankings struct {
  2. Keyword string `json:"Keyword"`
  3. GetCount uint32 `json:"Get_count"`
  4. Engine string `json:"Engine"`
  5. Locale string `json:"Locale"`
  6. Mobile bool `json:"Mobile"`
  7. }

答案3

得分: 1

使用json.Marshal() / json.MarshalIndent()时发生了一个问题。
它会覆盖现有文件,这在我的情况下是次优的。我只想向当前文件添加内容,并保留旧内容。

这段代码使用了一个字节缓冲区(bytes.Buffer类型)来写入数据。

这是我目前总结出来的代码:

  1. package srf
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "os"
  6. )
  7. func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
  8. // 将数据写入缓冲区
  9. buffer := new(bytes.Buffer)
  10. encoder := json.NewEncoder(buffer)
  11. encoder.SetIndent("", "\t")
  12. err := encoder.Encode(data)
  13. if err != nil {
  14. return 0, err
  15. }
  16. // 打开文件
  17. file, err := os.OpenFile(filedir, os.O_RDWR|os.O_CREATE, 0755)
  18. if err != nil {
  19. return 0, err
  20. }
  21. // 将缓冲区的数据写入文件
  22. n, err := file.Write(buffer.Bytes())
  23. if err != nil {
  24. return 0, err
  25. }
  26. return n, nil
  27. }

下面是调用该函数的代码,同时还包括了使用json.Marshal()json.MarshalIndent()覆盖文件的代码:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. minerals "./minerals"
  8. srf "./srf"
  9. )
  10. func main() {
  11. // Test 结构体的数组
  12. var SomeType [10]minerals.Test
  13. // 创建 10 个随机数据单元以进行写入
  14. for a := 0; a < 10; a++ {
  15. SomeType[a] = minerals.Test{
  16. Name: "Rand",
  17. Id: 123,
  18. A: "desc",
  19. Num: 999,
  20. Link: "somelink",
  21. People: []string{"John Doe", "Aby Daby"},
  22. }
  23. }
  24. // 向现有文件添加额外数据,或创建新文件
  25. n, err := srf.WriteDataToFileAsJSON(SomeType, "test2.json")
  26. if err != nil {
  27. log.Fatal(err)
  28. }
  29. fmt.Println("srf printed", n, "bytes to", "test2.json")
  30. // 覆盖之前的文件
  31. b, _ := json.MarshalIndent(SomeType, "", "\t")
  32. ioutil.WriteFile("test.json", b, 0644)
  33. }

为什么这很有用?
File.Write() 返回写入文件的字节数!因此,如果您想管理内存或存储,这非常完美。

WriteDataToFileAsJSON() 函数返回写入的字节数和错误信息。

英文:

An accourance happened by just using json.Marshal() / json.MarshalIndent().
It overwrites the existing file, which in my case was suboptimal. I just wanted to add content to current file, and keep old content.

This writes data through a buffer, with bytes.Buffer type.

This is what I gathered up so far:

  1. package srf
  2. import (
  3. &quot;bytes&quot;
  4. &quot;encoding/json&quot;
  5. &quot;os&quot;
  6. )
  7. func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
  8. //write data as buffer to json encoder
  9. buffer := new(bytes.Buffer)
  10. encoder := json.NewEncoder(buffer)
  11. encoder.SetIndent(&quot;&quot;, &quot;\t&quot;)
  12. err := encoder.Encode(data)
  13. if err != nil {
  14. return 0, err
  15. }
  16. file, err := os.OpenFile(filedir, os.O_RDWR|os.O_CREATE, 0755)
  17. if err != nil {
  18. return 0, err
  19. }
  20. n, err := file.Write(buffer.Bytes())
  21. if err != nil {
  22. return 0, err
  23. }
  24. return n, nil
  25. }

This is the execution of the function, together with the standard json.Marshal() or json.MarshalIndent() which overwrites the file

  1. package main
  2. import (
  3. &quot;encoding/json&quot;
  4. &quot;fmt&quot;
  5. &quot;io/ioutil&quot;
  6. &quot;log&quot;
  7. minerals &quot;./minerals&quot;
  8. srf &quot;./srf&quot;
  9. )
  10. func main() {
  11. //array of Test struct
  12. var SomeType [10]minerals.Test
  13. //Create 10 units of some random data to write
  14. for a := 0; a &lt; 10; a++ {
  15. SomeType[a] = minerals.Test{
  16. Name: &quot;Rand&quot;,
  17. Id: 123,
  18. A: &quot;desc&quot;,
  19. Num: 999,
  20. Link: &quot;somelink&quot;,
  21. People: []string{&quot;John Doe&quot;, &quot;Aby Daby&quot;},
  22. }
  23. }
  24. //writes aditional data to existing file, or creates a new file
  25. n, err := srf.WriteDataToFileAsJSON(SomeType, &quot;test2.json&quot;)
  26. if err != nil {
  27. log.Fatal(err)
  28. }
  29. fmt.Println(&quot;srf printed &quot;, n, &quot; bytes to &quot;, &quot;test2.json&quot;)
  30. //overrides previous file
  31. b, _ := json.MarshalIndent(SomeType, &quot;&quot;, &quot;\t&quot;)
  32. ioutil.WriteFile(&quot;test.json&quot;, b, 0644)
  33. }

Why is this useful?
File.Write() returns bytes written to the file! So this is perfect if you want to manage memory or storage.

  1. WriteDataToFileAsJSON() (numberOfBytesWritten, error)

huangapple
  • 本文由 发表于 2014年7月16日 08:39:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/24770403.html
匿名

发表评论

匿名网友

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

确定