Reputation: 2025
I'm having trouble figuring out how to load a "subsection" of JSON file into a map element. Background: I'm trying to unmarshal a somewhat complicated configuration file which has a strict structure, so I assume it's preferable to unmarshal into a "static" structure rather than into an interface{}.
Here's a simple JSON file for example:
{
"set1": {
"a":"11",
"b":"22",
"c":"33"
}
}
This code works:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type JSONType struct {
FirstSet ValsType `json:"set1"`
}
type ValsType struct {
A string `json:"a"`
B string `json:"b"`
C string `json:"c"`
}
func main() {
file, e := ioutil.ReadFile("./test1.json")
if e != nil {
fmt.Println("file error")
os.Exit(1)
}
var s JSONType
json.Unmarshal([]byte(file), &s)
fmt.Printf("\nJSON: %+v\n", s)
}
But this doesn't:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type JSONType struct {
FirstSet ValsType `json:"set1"`
}
type ValsType struct {
Vals map[string]string
}
func main() {
file, e := ioutil.ReadFile("./test1.json")
if e != nil {
fmt.Println("file error")
os.Exit(1)
}
var s JSONType
s.FirstSet.Vals = map[string]string{}
json.Unmarshal([]byte(file), &s)
fmt.Printf("\nJSON: %+v\n", s)
}
The Vals map isn't loaded. What am I doing wrong? Thanks for any help!
Here's a better example:
{
"set1": {
"a": {
"x": "11",
"y": "22",
"z": "33"
},
"b": {
"x": "211",
"y": "222",
"z": "233"
},
"c": {
"x": "311",
"y": "322",
"z": "333"
},
}
}
Code:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type JSONType struct {
FirstSet map[string]ValsType `json:"set1"`
}
type ValsType struct {
X string `json:"x"`
Y string `json:"y"`
Z string `json:"z"`
}
func main() {
file, e := ioutil.ReadFile("./test1.json")
if e != nil {
fmt.Println("file error")
os.Exit(1)
}
var s JSONType
json.Unmarshal([]byte(file), &s)
fmt.Printf("\nJSON: %+v\n", s)
}
Upvotes: 0
Views: 7550
Reputation: 48076
I believe that is because you have extra layer of indirection in your models.
type JSONType struct {
FirstSet map[string]string `json:"set1"`
}
Should suffice. if you specify map[string]string
the object in json is recognized as that map. You created a struct to wrap it but a blob of json like this;
{
"a":"11",
"b":"22",
"c":"33"
}
Actually can unmarshal directly into map[string]string
EDIT: Some other models based on the comment
type JSONType struct {
FirstSet map[string]Point `json:"set1"`
}
type Point struct {
X string `json:"x"`
Y string `json:"y"`
Z string `json:"z"`
}
This makes your 3-d point a statically typed struct which is fine. If you wanted to do the quick and dirty you could also just use map[string]map[string]string
which would give a map of maps so you could access the point values like FirstSet["a"]["x"]
and it would return "11"
.
Second edit; clearly I didn't read you code that closely since the above example is the same. Based on that I would guess you want the
FirstSet map[string]map[string]string `json:"set1"`
option. Though it's not entirely clear to me after your edit.
Upvotes: 4