Golang: JSON 综合案例(天气预报)

we create a tiny JSON client/server app in Go.

JSON 数据格式&改编版就不说了,这里主要记录读写,简单小案例,练习。

我现在有一个 JSON 数据文件,请给我生成一个自动生成的 struct 结构体。(手写也可以,但是太麻烦)
免得我自己去写 backquote 映射。可以借助 josn2go工具

但是对于嵌入式结构,不要嵌入定义,带出来单独定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
type weatherData struct {
LocationName string `json: locationName`
Weather string `json: weather`
Temperature int `json: temperature`
Celsius bool `json: celsius`
TempForecast []int `json: temp_forecast`
Wind windData `json: wind` //here
}

type windData struct {
Direction string `json: direction`
Speed int `json: speed`
}

然后读写代码如下:( ioutil.ReadAll 方法可能会占用大量机器内存)

1
2
3
4
5
6
7
8
9
10
11
12
13
type weatherData struct {
LocationName string `json: locationName`
Weather string `json: weather`
Temperature int `json: temperature`
Celsius bool `json: celsius`
TempForecast []int `json: temp_forecast`
Wind windData `json: wind` //here
}

type windData struct {
Direction string `json: direction`
Speed int `json: speed`
}

唯一可能需要注意的是, JSON Field 只映射 struct 中 exported,公有的字段。(指定的映射默认此规则)

然后读写代码如下:( ioutil.ReadAll 方法可能会占用大量机器内存)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)

type weatherData struct {
LocationName string `json: locationName`
Weather string `json: weather`
Temperature int `json: temperature`
Celsius bool `json: celsius`
TempForecast []int `json: temp_forecast`
Wind windData `json: wind`
}

type windData struct {
Direction string `json: direction`
Speed int `json: speed`
}

type loc struct {
Lat float32 `json: lat`
Lon float32 `json: lon`
}

func weatherHandler(w http.ResponseWriter, r *http.Request) {
location := loc{}

log.Println(r.Method)
jsn, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal("Error reading the body", err)
}

err = json.Unmarshal(jsn, &location)
if err != nil {
log.Fatal("Decoding error: ", err)
}

log.Printf("Received: %v\n", location)
weather := weatherData{
LocationName: "Zzyzx",
Weather: "cloudy",
Temperature: 31,
Celsius: true,
TempForecast: []int{30, 32, 29},
Wind: windData{
Direction: "S",
Speed: 20,
},
}

weatherJson, err := json.Marshal(weather)
if err != nil {
fmt.Fprintf(w, "Error: %s", err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(weatherJson)

}

func server() {
http.HandleFunc("/", weatherHandler)
http.ListenAndServe(":8080", nil)
}

func client() {
locJson, err := json.Marshal(loc{Lat: 35.14326, Lon: -116.104})
req, err := http.NewRequest("POST", "http://localhost:8080", bytes.NewBuffer(locJson))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
fmt.Println("Response: ", string(body))
resp.Body.Close()
}

func main() {
go server()
client()
}

代码和简单,跑一个客户端发送 location 给 服务端,服务端解析请求JSON段,然后打印;之后服务端回写一些JSON给client。专门用 client := &http.Client{} 建立一个客户端实例的原因是,既要发送,又要等着接收服务端的回写。

然后运行结果如下:

1
2
3
4
$ go run main.go
2018/03/16 15:27:34 POST
2018/03/16 15:27:34 Received: {35.14326 -116.104}
Response: {"LocationName":"Zzyzx","Weather":"cloudy","Temperature":31,"Celsius":true,"TempForecast":[30,32,29],"Wind":{"Direction":"S","Speed":20}}

结合 net/http, 练习了一下 encoding/json 感觉不错。(虽然数据都是 Mock 的)


Merlin 2018.3 更复杂的案例,可以参考 blog.golang.org/json-and-go

文章目录
|