I am not sure how to parse json to structures in Golang, It seem like it's easy, but I am having trouble getting the data from the file.
I know I have to declare the structures like this
type Title1 struct{
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
type Title2 struct{
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
// Read from the file
data, error := ioutil.ReadFile("file.json")
if error != nil{
log.Panic(error)
} else {
data := Title1{}
_ = json.Unmarshal([]byte(data), Title1)
log.Println("Opt1: " + Title1.Opt1)
}
}
{
"title1": {
"opt1": "..."
"opt2": "...",
"opt3": "...",
"opt4": "...",
}
"title2": {
"opt1": "..."
"opt2": "...",
"opt3": "...",
"opt4": "...",
}
}
But I don't know how to specify which title it should use.
There are couple of things you need to change first.
The json format is not correct. Some semicolons are missing. Without valid JSON input, the unmarshal will fail eventually. The correct format would be,
{
"title1": {
"opt1": "...",
"opt2": "...",
"opt3": "...",
"opt4": "..."
},
"title2": {
"opt1": "...",
"opt2": "...",
"opt3": "...",
"opt4": "..."
}
}
As your json contains both title1
and title2
field, you need a struct where both fields are available. One way to initialize the struct can be, (playground link)
type Title1 struct {
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
type Title2 struct {
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
type Data struct {
Title1 `json:"title1"`
Title2 `json:"title2"`
}
Furthermore, as the both title1
and title2
has the same fields. You can also do the following, (playground link)
type Title struct {
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
type Data struct {
Title1 Title `json:"title1"`
Title2 Title `json:"title2"`
}
In golang community, this json-to-go tool is very important.
In json.Unmarshal([]byte(data), Title1)
, using struct type Title1
will give you compilation error. This second parameter requires pointer of the struct type to unmarshal the input. So:
// data := Title1{}
data := Data{}
_ = json.Unmarshal([]byte(input), &data)
The most important part, never ignore errors. The error massages will give you direction to look where in case anything goes wrong.
if err := json.Unmarshal([]byte(input), &dataOutput); err != nil {
log.Panic(err)
}
So, after considering all the above changes, a working example is:
package main
import (
"encoding/json"
"io/ioutil"
"log"
)
type Title struct {
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
type Data struct {
Title1 Title `json:"title1"`
Title2 Title `json:"title2"`
}
func main() {
// Read from the file
input, error := ioutil.ReadFile("file.json")
if error != nil {
log.Panic(error)
} else {
data := Data{}
if err := json.Unmarshal([]byte(input), &data); err != nil {
log.Panic(err)
}
log.Println("Opt1: " + data.Title1.Opt1)
}
}
If "title1" and "title2" are arbitrary keys, then decode to a map:
type Title struct {
Opt1 string `json:"opt1"`
Opt2 string `json:"opt2"`
Opt3 string `json:"opt3"`
Opt4 string `json:"opt4"`
}
var m map[string]Title
err := json.Unmarshal(data, &m)
if err != nil {
// handle the error
}
log.Println("Title1.Opt1: " + m["title1"].Opt1)