如何在Go中解析json?

时间:2019-07-16 17:15:42

标签: json go

我不确定如何将json解析为Golang中的结构,这看起来很简单,但是我无法从文件中获取数据。

我知道我必须声明这样的结构

type Title1 struct{
  Opt1 string `json:"opt1"`
  Opt2 string `json:"opt2"`
  Opt3 string `json:"opt3"`
  Opt4 string `json:"opt4"`
}

type Title2 struct{
  Opt1 string `json:"opt1"`
  Opt2 string `json:"opt2"`
  Opt3 string `json:"opt3"`
  Opt4 string `json:"opt4"`
}
// Read from the file
data, error := ioutil.ReadFile("file.json")
  if error != nil{
    log.Panic(error)
  } else {
    data := Title1{}
    _ = json.Unmarshal([]byte(data), Title1)
    log.Println("Opt1: " + Title1.Opt1)
  }
}
{
  "title1": {
    "opt1": "..."
    "opt2": "...",
    "opt3": "...",
    "opt4": "...",
  }
  "title2": {
    "opt1": "..."
    "opt2": "...",
    "opt3": "...",
    "opt4": "...",
  }
}

但是我不知道如何指定应该使用哪个标题。

2 个答案:

答案 0 :(得分:0)

您需要首先更改几件事。

  1. json格式不正确。缺少一些分号。没有有效的JSON输入,解组将最终失败。正确的格式是

    {
      "title1": {
        "opt1": "...", 
        "opt2": "...",
        "opt3": "...",
        "opt4": "..."
      },
      "title2": {
        "opt1": "...",
        "opt2": "...",
        "opt3": "...",
        "opt4": "..."
      }
    }
    
  2. 由于您的json同时包含title1title2字段,因此您需要一个结构,其中两个字段均可用。初始化结构的一种方法可以是(playground link

    type Title1 struct {
        Opt1 string `json:"opt1"`
        Opt2 string `json:"opt2"`
        Opt3 string `json:"opt3"`
        Opt4 string `json:"opt4"`
    }
    
    type Title2 struct {
        Opt1 string `json:"opt1"`
        Opt2 string `json:"opt2"`
        Opt3 string `json:"opt3"`
        Opt4 string `json:"opt4"`
    }
    
    type Data struct {
        Title1 `json:"title1"`
        Title2 `json:"title2"`
    }
    

    此外,由于title1title2都具有相同的字段。您还可以执行以下操作((playground link

    type Title struct {
        Opt1 string `json:"opt1"`
        Opt2 string `json:"opt2"`
        Opt3 string `json:"opt3"`
        Opt4 string `json:"opt4"`
    }
    
    type Data struct {
        Title1 Title `json:"title1"`
        Title2 Title `json:"title2"`
    }
    

    在golang社区中,此json-to-go工具非常重要。

  3. json.Unmarshal([]byte(data), Title1)中,使用结构类型Title1将给您编译错误。第二个参数要求使用struct类型的指针来解组输入。所以:

    // data := Title1{} 
    data := Data{}
    _ = json.Unmarshal([]byte(input), &data)
    
  4. 最重要的部分永不忽略错误。错误消息将指导您确定万一出了什么问题。

    if err := json.Unmarshal([]byte(input), &dataOutput); err != nil {
        log.Panic(err)
    }
    

因此,在考虑了上述所有更改之后,一个有效的示例是:

package main

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

type Title struct {
    Opt1 string `json:"opt1"`
    Opt2 string `json:"opt2"`
    Opt3 string `json:"opt3"`
    Opt4 string `json:"opt4"`
}

type Data struct {
    Title1 Title `json:"title1"`
    Title2 Title `json:"title2"`
}

func main() {
    // Read from the file
    input, error := ioutil.ReadFile("file.json")
    if error != nil {
        log.Panic(error)
    } else {
        data := Data{}
        if err := json.Unmarshal([]byte(input), &data); err != nil {
            log.Panic(err)
        }
        log.Println("Opt1: " + data.Title1.Opt1)
    }
}

答案 1 :(得分:0)

如果“ title1”和“ title2”是任意键,则解码为地图:

type Title struct {
    Opt1 string `json:"opt1"`
    Opt2 string `json:"opt2"`
    Opt3 string `json:"opt3"`
    Opt4 string `json:"opt4"`
}

var m map[string]Title
err := json.Unmarshal(data, &m)
if err != nil {
    // handle the error
}

log.Println("Title1.Opt1: " + m["title1"].Opt1)

Try this on the Go Playground