将json字符串解组到具有结构本身一个元素的结构

将json字符串解组到具有结构本身一个元素的结构,json,go,struct,Json,Go,Struct,我是初学者,正在尝试解组以下json字符串 [{ "db": { "url": "mongodb://localhost", "port": "27000", "uname": "", "pass": "", "authdb": "", "replicas": [ { "rs01": { "url"

我是初学者,正在尝试解组以下json字符串

[{
    "db": {
        "url": "mongodb://localhost",
        "port": "27000",
        "uname": "",
        "pass": "",
        "authdb": "",
        "replicas": [
            {
                "rs01": {
                    "url":"mongodb://localhost",
                    "port": "27001",
                    "uname": "",
                    "pass": "",
                    "authdb": ""
                }
            },
            {
                "rs02": {
                    "url":"mongodb://localhost",
                    "port": "27002",
                    "uname": "",
                    "pass": "",
                    "authdb": ""
                }
            }
        ]
    }
}]
这是结构图

type DBS struct {
    URL      string `json:url`
    Port     string `json:port`
    Uname    string `json:uname`
    Pass     string `json:pass`
    Authdb   string `json:authdb`
    Replicas []DBS   `json:replicas`
}
这里是函数

func loadConfigs() []DBS {
    var config []DBS
    raw, err := ioutil.ReadFile("./config.json")
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }

    json.Unmarshal(raw, &config)
    return config
}
函数正在返回

{     []}

您的JSON输入不是
DBS
的一部分,因为还有另一个JSON对象包装器,
DBS
的值属于属性
“db”

更深入地说,
“replicaps”
是一个JSON数组,其中的对象持有不同的键,它们的值可由
DBS
表示

因此,为了全面描述JSON,您需要某种“动态”类型。例如,地图就是这样一种动态类型

因此,可以使用以下类型对原始JSON输入进行完全建模:
[]map[string]DBS
。这是一个映射片段,因为JSON输入包含一个JSON数组。map键可以为任何属性名建模,值是由
DBS
struct建模的JSON对象

请参阅此完全解析JSON输入的示例:

type DBS struct {
    URL      string           `json:"url"`
    Port     string           `json:"port"`
    Uname    string           `json:"uname"`
    Pass     string           `json:"pass"`
    Authdb   string           `json:"authdb"`
    Replicas []map[string]DBS `json:"replicas"`
}

func main() {
    var dbs []map[string]DBS
    if err := json.Unmarshal([]byte(src), &dbs); err != nil {
        panic(err)
    }
    fmt.Printf("%+v", dbs)
}
请注意正确的链接(例如
json:“url”

输出(在上尝试):

[map[db:{URL:mongodb://localhost 端口:27000 Uname:Pass:Authdb:Replicas:[map[rs01:{URL:mongodb://localhost 端口:27001 Uname:Pass:Authdb:replications:[]}]map[rs02:{URL:mongodb://localhost 端口:27002 Uname:Pass:Authdb:Replicas:[]}]]]

请注意,您可以进一步对第一个级别进行建模,该级别总是
“db”
,我们可以切换到指针(我在第一个示例中使用了非指针,因此打印的结果是可读的):

输出(在上尝试):


您的JSON输入不是
DBS
的一部分,因为还有另一个JSON对象包装器,
DBS
的值属于属性
“db”

更深入地说,
“replicaps”
是一个JSON数组,其中的对象持有不同的键,它们的值可由
DBS
表示

因此,为了全面描述JSON,您需要某种“动态”类型。例如,地图就是这样一种动态类型

因此,可以使用以下类型对原始JSON输入进行完全建模:
[]map[string]DBS
。这是一个映射片段,因为JSON输入包含一个JSON数组。map键可以为任何属性名建模,值是由
DBS
struct建模的JSON对象

请参阅此完全解析JSON输入的示例:

type DBS struct {
    URL      string           `json:"url"`
    Port     string           `json:"port"`
    Uname    string           `json:"uname"`
    Pass     string           `json:"pass"`
    Authdb   string           `json:"authdb"`
    Replicas []map[string]DBS `json:"replicas"`
}

func main() {
    var dbs []map[string]DBS
    if err := json.Unmarshal([]byte(src), &dbs); err != nil {
        panic(err)
    }
    fmt.Printf("%+v", dbs)
}
请注意正确的链接(例如
json:“url”

输出(在上尝试):

[map[db:{URL:mongodb://localhost 端口:27000 Uname:Pass:Authdb:Replicas:[map[rs01:{URL:mongodb://localhost 端口:27001 Uname:Pass:Authdb:replications:[]}]map[rs02:{URL:mongodb://localhost 端口:27002 Uname:Pass:Authdb:Replicas:[]}]]]

请注意,您可以进一步对第一个级别进行建模,该级别总是
“db”
,我们可以切换到指针(我在第一个示例中使用了非指针,因此打印的结果是可读的):

输出(在上尝试):


如果出于某种原因,您无法使用现有的
DBS
结构,那么您也可以编写自己的
json.Unmarshaler
实现

(在下面的示例中,我确实稍微更改了结构以跟踪名称/键,但这是可选的,不需要进行解组。)


如果出于某种原因,您一直使用现有的
DBS
结构,您也可以编写自己的
json.Unmarshaler
实现

(在下面的示例中,我确实稍微更改了结构以跟踪名称/键,但这是可选的,不需要进行解组。)


您没有检查从解组返回的错误。您没有检查从解组返回的错误。
&{URL:mongodb://localhost Port:27000 Uname: Pass: Authdb: Replicas:[map[rs01:0x10538200] map[rs02:0x10538240]]}
rs01: &{URL:mongodb://localhost Port:27001 Uname: Pass: Authdb: Replicas:[]}
rs02: &{URL:mongodb://localhost Port:27002 Uname: Pass: Authdb: Replicas:[]}
type DBS struct {
    name     string

    URL      string `json:url`
    Port     string `json:port`
    Uname    string `json:uname`
    Pass     string `json:pass`
    Authdb   string `json:authdb`
    Replicas []DBS  `json:replicas`
}

func (db *DBS) UnmarshalJSON(data []byte) error {
    raw := map[string]json.RawMessage{}
    if err := json.Unmarshal(data, &raw); err != nil {
        return err
    }
    if len(raw) > 1 {
        return fmt.Errorf("fail")
    }

    type _DBS DBS
    _db := (*_DBS)(db)
    for name, v := range raw {
        db.name = name
        return json.Unmarshal(v, _db)
    }
    return nil
}