1

我正在解析一个具有不寻常结构的 JSON 文件,如下所示:

{
    "394885": 
    {
        "record": 
        {
            "student_name": "Daryl Jones",
            "student_number": 123884,
            "student_dob": "12/10/1982",
            "student_email": "djones@school.ac.uk",
        }    
    },
}

我一直在研究一些代码演示,但我想将它们全部放入一个结构中,然后我计划通过我猜的对象名称的数字字符串进行搜索?

我不擅长 JSON 或 Go,这是我迄今为止编写的代码:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

type id struct {
    recordid string
    record   []record
}

type record struct {
    name   string
    number uint32
    dob    string
    email  string
}

func main() {
    jsonFile, err := os.Open("/home/emyrw/development/go/src/json_processor/demo.json")
    if err != nil {
        fmt.Println(err)
    } else {
        var records id

        byteValue, _ := ioutil.ReadAll(jsonFile)
        json.Unmarshal(byteValue, &records)
        fmt.Println(records)

        fmt.Println("opened demo.json")
        defer jsonFile.Close()
    }
}

我不确定我是否做对了,但我会重视任何人提供的任何提示或建议。我一直在谷歌搜索,但我发现没有一个样本非常适合我的场景。

4

4 回答 4

1

首先,您的 JSON 无效。与 GoLang 结构不同,您不需要放在,最终对象之后。

{“394885”:{“记录”:{“学生姓名”:“达里尔琼斯”,“学生编号”:123884,“学生日期”:“1982 年 12 月 10 日”,“学生电子邮件”:“djones@school.ac.uk " }
} }

其次, var records应该对 JSON 进行精确建模,方法是完全按照 JSON 对象中的名称命名结构中的字段,或者使用属性。

JSON 的外部不是类型id,而是类型map[string]id

id没有recordid字段,但是有record字段,但是,如果要将 JSON 序列化到结构中,则必须导出结构的字段(以大写开头)。

这就是属性派上用场的地方,

type id struct {
    Record []record `json:"record"`
}

record结构相同,

type record struct {
    Name string `json:"student_name"`
    Email string `json:"student_email"`
    // You get the idea...
}

第三,您defer在打开文件后立即放置语句,将其放在块的末尾会破坏目的。

于 2019-03-03T18:50:23.910 回答
1

声明与数据结构匹配的 Go 类型。JSON 数据具有三个级别的对象。使用映射来表示 JSON 中的顶级对象,因为顶级对象具有任意键。将结构用于 JSON 中的较低级别对象。

使用 JSON 字段标签将 JSON 中使用的蛇案例名称映射到更惯用的 Go 名称。 导出字段,以便 JSON 包可以访问它们。

有关json/encoding 包如何使用字段标签以及导出字段的要求的信息,请参阅Marshal函数文档。

type Record struct {
    Name   string `json:"student_name"`
    Number uint32 `json:"student_number"`
    DOB    string `json:"student_dob"`
    Email  string `json:"student_email"`
}

type ID struct {
    Record Record
}

...

var records map[string]ID
err := json.Unmarshal(jsonFile, &records)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%#v\n", records)

在操场上运行它

于 2019-03-03T19:52:44.377 回答
0

jsonquery包可以很容易地从 JSON 文档中提取数据,它不依赖于定义的结构对象。

func main() {
    s := `{
        "394885": 
        {
            "record": 
            {
                "student_name": "Daryl Jones",
                "student_number": 123884,
                "student_dob": "12/10/1982",
                "student_email": "djones@school.ac.uk"
            }    
        }
    }`
    doc, err := jsonquery.Parse(strings.NewReader(s))
    if err != nil {
        panic(err)
    }
    nodes := jsonquery.Find(doc, "*")
    for _, n := range nodes {
        fmt.Printf("id: %s \n", n.Data)
        name := jsonquery.FindOne(n, "//student_name") // Find student name node
        fmt.Printf("student name: %s\n", name.InnerText())
        number := jsonquery.FindOne(n, "//student_number") // Find node for student number
        fmt.Printf("student number: %s\n", number.InnerText())
    }
}

于 2019-03-05T05:56:13.957 回答
-2

您可以将此结构用于您的 id 类型

type id struct {
    record map[string]record
}

编辑

这是带有一些解释的工作解决方案:

由于您有一个多级 json,您可以将其解析为嵌套结构。

{
        "student_name": "Daryl Jones",
        "student_number": 123884,
        "student_dob": "12/10/1982",
        "student_email": "djones@school.ac.uk"
} 

要解析 json 的这一部分,你需要这个结构

type record struct {
    Name   string `json:"student_name"`
    Number uint32 `json:"student_number"`
    Dob    string `json:"student_dob"`
    Email  string `json:"student_email"`
}

必须导出字段(以大写字母开头)并具有与 json 属性匹配的 json 标记。

{
    "record": 
    {
        "student_name": "Daryl Jones",
        "student_number": 123884,
        "student_dob": "12/10/1982",
        "student_email": "djones@school.ac.uk"
    }    
}

要使这部分工作,您需要一个像这样的嵌套结构

type id struct {
     Record record
}

再次导出文件名,但由于它与您的 json 属性匹配,因此您不需要该标签。

{
"394885": 
  {
    "record": 
    {
        "student_name": "Daryl Jones",
        "student_number": 123884,
        "student_dob": "12/10/1982",
        "student_email": "djones@school.ac.uk"
    }    
  }
}

由于顶级属性名称是学生 ID,因此您可以使用映射而不是结构

 var records map[string]id 

并确保您没有尾随逗号,因为 json 规范中不允许这样做

于 2019-03-03T17:50:26.043 回答