jianfeng
jianfeng

Reputation: 2590

How do I parse this JSON-string in Go?

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)

Upvotes: 2

Views: 3419

Answers (2)

Alexander Bauer
Alexander Bauer

Reputation: 11083

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!

Upvotes: 3

peterSO
peterSO

Reputation: 166529

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

Upvotes: 6

Related Questions