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

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

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

问题

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

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

代码:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type Rankings struct {
    Keyword  string `json:"keyword"`
    GetCount uint32 `json:"get_count"`
    Engine   string `json:"engine"`
    Locale   string `json:"locale"`
    Mobile   bool   `json:"mobile"`
}

func main() {
    var jsonBlob = []byte(`
        {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
    `)
    rankings := Rankings{}
    err := json.Unmarshal(jsonBlob, &rankings)
    if err != nil {
        // nozzle.printError("opening config file", err.Error())
    }

    rankingsJson, _ := json.Marshal(rankings)
    err = ioutil.WriteFile("output.json", rankingsJson, 0644)
    fmt.Printf("%+v", rankings)
}

屏幕上的输出:

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

输出到Json文件:

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

期望的输出到Json文件:

{"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:

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

type Rankings struct {
	Keyword  string `json:"keyword"`
	GetCount uint32 `json:"get_count"`
	Engine   string `json:"engine"`
	Locale   string `json:"locale"`
	Mobile   bool   `json:"mobile"`
}

func main() {
	var jsonBlob = []byte(`
		{"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
	`)
	rankings := Rankings{}
	err := json.Unmarshal(jsonBlob, &rankings)
	if err != nil {
		// nozzle.printError("opening config file", err.Error())
	}

	rankingsJson, _ := json.Marshal(rankings)
	err = ioutil.WriteFile("output.json", rankingsJson, 0644)
	fmt.Printf("%+v", rankings)
}

Output on screen:

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

Output to Json File:

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

Desired Output to Json File:

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

答案1

得分: 30

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

所以:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type Rankings struct {
    Keyword  string 
    GetCount uint32 
    Engine   string 
    Locale   string 
    Mobile   bool   
}

func main() {
    var jsonBlob = []byte(`
        {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
    `)
    rankings := Rankings{}
    err := json.Unmarshal(jsonBlob, &rankings)
    if err != nil {
        // nozzle.printError("opening config file", err.Error())
    }

    rankingsJson, _ := json.Marshal(rankings)
    err = ioutil.WriteFile("output.json", rankingsJson, 0644)
    fmt.Printf("%+v", rankings)
}

结果为:

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

输出文件为:

{"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:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type Rankings struct {
    Keyword  string 
    GetCount uint32 
    Engine   string 
    Locale   string 
    Mobile   bool   
}

func main() {
    var jsonBlob = []byte(`
        {"keyword":"hipaa compliance form", "get_count":157, "engine":"google", "locale":"en-us", "mobile":false}
    `)
    rankings := Rankings{}
    err := json.Unmarshal(jsonBlob, &rankings)
    if err != nil {
        // nozzle.printError("opening config file", err.Error())
    }

    rankingsJson, _ := json.Marshal(rankings)
    err = ioutil.WriteFile("output.json", rankingsJson, 0644)
    fmt.Printf("%+v", rankings)
}

Results in:

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

And the file output is:

{"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格式:

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

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

英文:

Try to change the json format in the struct

type Rankings struct {
    Keyword  string `json:"Keyword"`
    GetCount uint32 `json:"Get_count"`
    Engine   string `json:"Engine"`
    Locale   string `json:"Locale"`
    Mobile   bool   `json:"Mobile"`
}

答案3

得分: 1

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

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

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

package srf

import (
	"bytes"
	"encoding/json"
	"os"
)

func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
	// 将数据写入缓冲区
	buffer := new(bytes.Buffer)
	encoder := json.NewEncoder(buffer)
	encoder.SetIndent("", "\t")

	err := encoder.Encode(data)
	if err != nil {
		return 0, err
	}

	// 打开文件
	file, err := os.OpenFile(filedir, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		return 0, err
	}

	// 将缓冲区的数据写入文件
	n, err := file.Write(buffer.Bytes())
	if err != nil {
		return 0, err
	}

	return n, nil
}

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

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"

	minerals "./minerals"
	srf "./srf"
)

func main() {
	// Test 结构体的数组
	var SomeType [10]minerals.Test

	// 创建 10 个随机数据单元以进行写入
	for a := 0; a < 10; a++ {
		SomeType[a] = minerals.Test{
			Name:   "Rand",
			Id:     123,
			A:      "desc",
			Num:    999,
			Link:   "somelink",
			People: []string{"John Doe", "Aby Daby"},
		}
	}

	// 向现有文件添加额外数据,或创建新文件
	n, err := srf.WriteDataToFileAsJSON(SomeType, "test2.json")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("srf printed", n, "bytes to", "test2.json")

	// 覆盖之前的文件
	b, _ := json.MarshalIndent(SomeType, "", "\t")
	ioutil.WriteFile("test.json", b, 0644)
}

为什么这很有用?
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:

package srf

import (
	&quot;bytes&quot;
	&quot;encoding/json&quot;
	&quot;os&quot;
)

func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
	//write data as buffer to json encoder
	buffer := new(bytes.Buffer)
	encoder := json.NewEncoder(buffer)
	encoder.SetIndent(&quot;&quot;, &quot;\t&quot;)

	err := encoder.Encode(data)
	if err != nil {
		return 0, err
	}
	file, err := os.OpenFile(filedir, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		return 0, err
	}
	n, err := file.Write(buffer.Bytes())
	if err != nil {
		return 0, err
	}
	return n, nil
}

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

package main

import (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;

	minerals &quot;./minerals&quot;
	srf &quot;./srf&quot;
)

func main() {

	//array of Test struct
	var SomeType [10]minerals.Test

	//Create 10 units of some random data to write
	for a := 0; a &lt; 10; a++ {
		SomeType[a] = minerals.Test{
			Name:   &quot;Rand&quot;,
			Id:     123,
			A:      &quot;desc&quot;,
			Num:    999,
			Link:   &quot;somelink&quot;,
			People: []string{&quot;John Doe&quot;, &quot;Aby Daby&quot;},
		}
	}

	//writes aditional data to existing file, or creates a new file
	n, err := srf.WriteDataToFileAsJSON(SomeType, &quot;test2.json&quot;)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(&quot;srf printed &quot;, n, &quot; bytes to &quot;, &quot;test2.json&quot;)
	
	//overrides previous file
	b, _ := json.MarshalIndent(SomeType, &quot;&quot;, &quot;\t&quot;)
	ioutil.WriteFile(&quot;test.json&quot;, b, 0644)

}

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

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:

确定