如何在Go中解析这个JSON字符串?

huangapple go评论89阅读模式
英文:

How do I parse this JSON-string in Go?

问题

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

英文:

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)

答案1

得分: 6

configs的地址传递给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}}
英文:

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

答案2

得分: 3

为了在@peterSO的答案基础上进行改进,如果你想要一些花哨的东西,encoding/json包有Decoder类型,它允许你直接从io.Reader解码JSON,而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。如果你只是做一些简单的事情并想避免这种情况,这可能是不必要的,但还是要知道这一点。

祝你好运!

英文:

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!

huangapple
  • 本文由 发表于 2013年2月5日 22:22:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/14709713.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定