通过Go来分析和创建JSON

一、分析JSON

首先了解一下JSON的语法规则

JSON 语法是 JavaScript 对象表示语法的子集。

  1. 数据在名称/值对中
  2. 数据由逗号分隔
  3. 大括号保存对象
  4. 中括号保存数组

把结构映射到JSON只有一个通用规则:对于名字为的JSON键,用户只需要在结构里创建一个任意名字的字段,并将该字段的结构标签设置为json:"<name>",就可以把JSON键的值存储到这个字段里面。

下面是要分析的JSON文件

{
  "id":1,
  "content":"Hello World",
  "author":{
    "id":2,
    "name":"Sau She"
  },
  "comments":[
    {
      "id":3,
      "content":"Have a great day!",
      "author":"Adam"
    },
    {
      "id":4,
      "content":"How are you today!",
      "author":"Betty"
    }
  ]
}

下面给出分析程序

package main

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

type Post struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author Author `json:"author"`
    Comments []Comment `json:"comments"`
}

type Author struct {
    Id  int `json:"id"`
    Name string `json:"name"`
}

type Comment struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author string `json:"author"`
}

func main() {
    file, err := os.Open("src/text/json/post.json")
    if err != nil {
        log.Fatalf("Error opening JSON file %v",err)
        return
    }
    defer file.Close()
    bytes, err := ioutil.ReadAll(file)
    if err != nil {
        log.Fatalf("Error reading JSON file %v",err)
        return
    }
    var post Post
    json.Unmarshal(bytes,&post)
    fmt.Println(post)
}

用户出了可以用Unmarshal函数来解封JSON,还可以使用Decoder手动地将JSON数据解码到结构体里面,以此来处理流式的JSON数据。

package main

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

type Post struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author Author `json:"author"`
    Comments []Comment `json:"comments"`
}

type Author struct {
    Id  int `json:"id"`
    Name string `json:"name"`
}

type Comment struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author string `json:"author"`
}

func main() {
    file, err := os.Open("src/text/json/post.json")
    if err != nil {
        log.Fatalf("Error opening JSON file %v",err)
        return
    }
    defer file.Close()
    decoder := json.NewDecoder(file)
    for  {
        var post Post
        err := decoder.Decode(&post)
        if err == io.EOF {
            break
        }
        if err != nil{
            log.Fatalf("Error decoding JSON  %v",err)
            return
        }
    }
}

最后,在面对JSON数据时,我们可以根据输入决定使用Decode还是Unmarshal:如果JSON数据来源是io.Reader流,如http.Request的Body,那么使用Decoder更好;如果JSON数据来源于字符串或者是内存的某个地方,那么使用Unmarshal更好。

二、创建JSON

package main

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

type Post struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author Author `json:"author"`
    Comments []Comment `json:"comments"`
}

type Author struct {
    Id  int `json:"id"`
    Name string `json:"name"`
}

type Comment struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author string `json:"author"`
}

func main() {
    post := Post{
        Id:1,
        Content:"Hello World!",
        Author:Author{
            Id:2,
            Name:"Sau Sheong",
        },
        Comments: []Comment{{
            Id:1,
            Content:"i love sz",
            Author:"zhu",
        },{
            Id:2,
            Content:"i love sh",
            Author:"liu",
        }},
    }
    output, err := json.MarshalIndent(&post,"","\t")
    if err != nil {
        log.Fatalf("Error marshalling to JSON  %v",err)
        return
    }
    err = ioutil.WriteFile("src/text/json/post2.json",output,0644)
    if err != nil {
        log.Fatalf("Error writing JSON to file  %v",err)
        return
    }
}

让我看看post2.json文件里面的内容

{
    "id": 1,
    "content": "Hello World!",
    "author": {
        "id": 2,
        "name": "Sau Sheong"
    },
    "comments": [
        {
            "id": 1,
            "content": "i love sz",
            "author": "zhu"
        },
        {
            "id": 2,
            "content": "i love sh",
            "author": "liu"
        }
    ]
}

我们也可通过编码器手动将Go结构编码为JSON数据。

package main

import (
    "encoding/json"
    "log"
    "os"
)

type Post struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author Author `json:"author"`
    Comments []Comment `json:"comments"`
}

type Author struct {
    Id  int `json:"id"`
    Name string `json:"name"`
}

type Comment struct {
    Id int `json:"id"`
    Content string `json:"content"`
    Author string `json:"author"`
}

func main() {
    post := Post{
        Id:1,
        Content:"Hello World!",
        Author:Author{
            Id:2,
            Name:"Sau Sheong",
        },
        Comments: []Comment{{
            Id:1,
            Content:"i love sz",
            Author:"zhu",
        },{
            Id:2,
            Content:"i love sh",
            Author:"liu",
        }},
    }
    jsonFile, err := os.Create("src/text/json/post3.json")
    if err != nil {
        log.Fatalf("Error Create JSON to file  %v",err)
        return
    }
    encoder := json.NewEncoder(jsonFile)
    encoder.SetIndent("","\t")
    encoder.Encode(&post)
    if err != nil {
        log.Fatalf("Error encoding JSON to file  %v",err)
        return
    }
}

程序会创建一个用于存储JSON数据的JSON文件,并通过把这个文件传递给NewEncoder函数来创建一个编码器。接着,程序会调用编码器的Encode方法,并向其传递一个指向Post结构的引用。在此以后,Encode方法会从结构里面提取数据并将其编码为JSON数据,然后把这些JSON数据写入到文件里面。

1 个评论

https://mholt.github.io/json-to-go

要回复文章请先登录注册