如何在Go中解析json?

I am not sure how to parse json to structures in Golang, It seem like it's easy, but I am having trouble getting the data from the file.

I know I have to declare the structures like this

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": "...",
  }
}

But I don't know how to specify which title it should use.

There are couple of things you need to change first.

  1. The json format is not correct. Some semicolons are missing. Without valid JSON input, the unmarshal will fail eventually. The correct format would be,

    {
      "title1": {
        "opt1": "...", 
        "opt2": "...",
        "opt3": "...",
        "opt4": "..."
      },
      "title2": {
        "opt1": "...",
        "opt2": "...",
        "opt3": "...",
        "opt4": "..."
      }
    }
    
  2. As your json contains both title1 and title2 field, you need a struct where both fields are available. One way to initialize the struct can be, (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"`
    }
    

    Furthermore, as the both title1 and title2 has the same fields. You can also do the following, (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"`
    }
    

    In golang community, this json-to-go tool is very important.

  3. In json.Unmarshal([]byte(data), Title1), using struct type Title1 will give you compilation error. This second parameter requires pointer of the struct type to unmarshal the input. So:

    // data := Title1{} 
    data := Data{}
    _ = json.Unmarshal([]byte(input), &data)
    
  4. The most important part, never ignore errors. The error massages will give you direction to look where in case anything goes wrong.

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

So, after considering all the above changes, a working example is:

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

If "title1" and "title2" are arbitrary keys, then decode to a map:

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.