2

The JSON-string in question looks like this:

{
"development":{
    "connector":[
         {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "wsPort":3050},
         {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "wsPort":3051},
         {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "wsPort":3052}
     ],
    "chat":[
         {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
         {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
         {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
    ],
    "gate":[
     {"id": "gate-server-1", "host": "127.0.0.1", "wsPort": 3014}
]
},
"production":{
   "connector":[
         {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "wsPort":3050},
         {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "wsPort":3051},
         {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "wsPort":3052}
     ],
    "chat":[
         {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
         {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
         {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
    ],
    "gate":[
     {"id": "gate-server-1", "host": "127.0.0.1", "wsPort": 3014}
]
}
}

and I want to parse it with code like this:

package config

import(
    "sync"
    "io/ioutil"
    "encoding/json"
    "errors"
    "log"
)

type Service struct {
    Id string `json:"id"`
    Host string `json:"host"`
    Port uint `json:"port"`
    QueryPort uint `json:"queryPort"`
    WsPort uint `json:"wsPort"`
    ServiceType string 
}

type Config struct {
    Services []Service
    Master Service
    Mutex sync.RWMutex
}

func LoadServers(filepath, env string) (*Config, error) {
    // 读取文件
    content, err := ioutil.ReadFile(filepath)
    if err != nil {
        return nil, err
    }

    configs := make(map[string]map[string][]Service, 0)
    err = json.Unmarshal(content, configs)
    if err != nil {
        return nil, err
    }
}

I expect my code to parse this JSON-string to a map[string]map[string][]Service.

but It shows the error:

json: Unmarshal(non-pointer map[string]map[string][]config.Service)
2
  • Have you looked at the type decoder example here golang.org/pkg/encoding/json Commented Feb 5, 2013 at 14:28
  • I have look at the article, but I think the diffucutity in my example is I want to use map to parse the json but not object. Commented Feb 5, 2013 at 14:31

2 Answers 2

6

Pass the address of configs to json.Unmarshal. For example,

configs := make(map[string]map[string][]Service, 0)
err = json.Unmarshal(content, &configs)
if err != nil {
    return nil, err
}
fmt.Println(configs)

Output:

map[production:map[connector:[{connector-server-1 127.0.0.1 4050 0 3050 } {connector-server-2 127.0.0.1 4051 0 3051 } {connector-server-3 127.0.0.1 4052 0 3052 }] gate:[{gate-server-1 127.0.0.1 0 0 3014 }] chat:[{chat-server-1 127.0.0.1 6050 0 0 } {chat-server-2 127.0.0.1 6051 0 0 } {chat-server-3 127.0.0.1 6052 0 0 }]] development:map[chat:[{chat-server-1 127.0.0.1 6050 0 0 } {chat-server-2 127.0.0.1 6051 0 0 } {chat-server-3 127.0.0.1 6052 0 0 }] gate:[{gate-server-1 127.0.0.1 0 0 3014 }] connector:[{connector-server-1 127.0.0.1 4050 0 3050 } {connector-server-2 127.0.0.1 4051 0 3051 } {connector-server-3 127.0.0.1 4052 0 3052 }]]]
&{[] {  0 0 0 } {{0 0} 0 0 0 0}}
Sign up to request clarification or add additional context in comments.

Comments

3

To build on @peterSO's answer, if you are up for something fancy, the encoding/json package has the Decoder type, which allows you to decode JSON directly from an io.Reader, which is an interface that os.File satisfies.

This would allow you to use the os package, rather than io/ioutil, which could save you an import (seeing as ioutil already imports os.)

package main

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

func main() {
    pathToFile := "jsondata.txt"

    file, err := os.OpenFile(pathToFile, os.O_RDONLY, 0644)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    configs := make(map[string]map[string][]Service, 0)
    err = json.NewDecoder(file).Decode(&configs)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

This way, you can decode JSON directly from a file or data stream. It's probably unnecessary if you're doing something simple and want to avoid this sort of thing, but nonetheless something to be aware of.

Good luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.