2

有问题的 JSON 字符串如下所示:

{
"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}
]
}
}

我想用这样的代码解析它:

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
    }
}

我希望我的代码将此 JSON 字符串解析为map[string]map[string][]Service.

但它显示错误:

json: Unmarshal(non-pointer map[string]map[string][]config.Service)
4

2 回答 2

6

传递configsto的地址json.Unmarshal。例如,

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

输出:

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}}
于 2013-02-05T15:05:04.273 回答
3

以@peterSO 的回答为基础,如果您想要一些花哨的东西,该encoding/json包具有Decoder类型,它允许您直接从 解码 JSON io.Reader,这是一个os.File满足的接口。

这将允许您使用os包,而不是io/ioutil,这可以为您节省导入(视为ioutil已经导入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)
    }
}

这样,您可以直接从文件或数据流中解码 JSON。如果您正在做一些简单的事情并想避免这种事情,这可能是不必要的,但仍然需要注意一些事情。

祝你好运!

于 2013-02-05T20:40:31.707 回答