问题:

提供天气信息的网站有很多,每家的数据及格式都不同,为了适配各种不同的天气接口,写了如下程序。

代码如下:

  1. package main
  2.  
  3. import (
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. )
  11.  
  12. var s string = `
  13. {
  14. "error": ,
  15. "status": "success",
  16. "date": "2015-03-26",
  17. "results": [
  18. {
  19. "test": [
  20. [
  21. "fuck",
  22. "shit"
  23. ],
  24. {
  25. "ao": "xxx"
  26. },
  27. "vfe"
  28. ],
  29. "currentCity": "郑州",
  30. "pm25": "",
  31. "index": [
  32. {
  33. "title": "穿衣",
  34. "zs": "较冷",
  35. "tipt": "穿衣指数",
  36. "des": "建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。"
  37. },
  38. {
  39. "title": "洗车",
  40. "zs": "不宜",
  41. "tipt": "洗车指数",
  42. "des": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
  43. },
  44. {
  45. "title": "旅游",
  46. "zs": "适宜",
  47. "tipt": "旅游指数",
  48. "des": "温度适宜,又有较弱降水和微风作伴,会给您的旅行带来意想不到的景象,适宜旅游,可不要错过机会呦!"
  49. },
  50. {
  51. "title": "感冒",
  52. "zs": "少发",
  53. "tipt": "感冒指数",
  54. "des": "各项气象条件适宜,无明显降温过程,发生感冒机率较低。"
  55. },
  56. {
  57. "title": "运动",
  58. "zs": "较不宜",
  59. "tipt": "运动指数",
  60. "des": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意保暖并携带雨具。"
  61. },
  62. {
  63. "title": "紫外线强度",
  64. "zs": "最弱",
  65. "tipt": "紫外线强度指数",
  66. "des": "属弱紫外线辐射天气,无需特别防护。若长期在户外,建议涂擦SPF在8-12之间的防晒护肤品。"
  67. }
  68. ],
  69. "weather_data": [
  70. {
  71. "date": "周四 03月26日 (实时:12℃)",
  72. "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/zhenyu.png",
  73. "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
  74. "weather": "阵雨转多云",
  75. "wind": "微风",
  76. "temperature": "12 ~ 4℃"
  77. },
  78. {
  79. "date": "周五",
  80. "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
  81. "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png",
  82. "weather": "晴",
  83. "wind": "微风",
  84. "temperature": "16 ~ 8℃"
  85. },
  86. {
  87. "date": "周六",
  88. "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
  89. "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
  90. "weather": "晴转多云",
  91. "wind": "微风",
  92. "temperature": "22 ~ 9℃"
  93. },
  94. {
  95. "date": "周日",
  96. "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
  97. "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png",
  98. "weather": "晴",
  99. "wind": "微风",
  100. "temperature": "25 ~ 11℃"
  101. }
  102. ]
  103. }
  104. ]
  105. }
  106. `
  107.  
  108. // 天气
  109. type Weather struct {
  110. Error_Code string `json:"error_code"` //错误码 0没有错误
  111. Status string `json:"status"` // 状态描述, success 成功
  112. Result Result `json:"result"` // 天气状况
  113. }
  114.  
  115. // 天气结果
  116. type Result struct {
  117. Now Real
  118. LivingIndex []Indicate `json:"living_index"` //生活指数
  119. Future []ForeCast `json:"future"` //未来几天的预报,包括当天
  120. }
  121.  
  122. // 实时报告
  123. type Real struct {
  124. City string `json:"city"` // 城市
  125. Temperature string `json:"temperature"` // 当前温度
  126. WindDirection string `json:"wind_direction"` // 风向
  127. WindStrength string `json:"wind_strength"` // 风强度
  128. Humidity string `json:"humidity"` // 湿度
  129. PM25 string `json:"pm25"` // PM2.5
  130. }
  131.  
  132. // 预报
  133. type ForeCast struct {
  134. Temperature string `json:"temperature"` // 温度范围
  135. Weather string `json:"weather"` // 天气 (晴,多云,阴转多云)
  136. Wind string `json:"wind"` // 风向和强度
  137. Week string `json:"week"` // 星期几
  138. Date string `json:"date"` // 日期
  139. }
  140.  
  141. type Indicate struct {
  142. Title string `json:"titile"` // 指数标题
  143. Status string `json:"status"` //指数状态 (适宜,不宜)
  144. Description string `json:"desc"` //描述信息
  145. }
  146.  
  147. func NewWeather() *Weather {
  148. return NewWeatherWithNum(, )
  149. }
  150.  
  151. func NewWeatherWithNum(livingIndexNum, forecastNum int) *Weather {
  152. w := &Weather{}
  153. w.Result.LivingIndex = make([]Indicate, livingIndexNum)
  154. w.Result.Future = make([]ForeCast, forecastNum)
  155. return w
  156. }
  157.  
  158. type ElementExtractor struct {
  159. Err error
  160. m map[string]interface{}
  161. r *regexp.Regexp
  162. }
  163.  
  164. func NewElementExtractor(jsonString string) *ElementExtractor {
  165. ee := &ElementExtractor{r: regexp.MustCompile(`(.*)\[(\d+)\]+`)}
  166. ee.Err = json.Unmarshal([]byte(jsonString), &ee.m)
  167. return ee
  168. }
  169.  
  170. func (ee *ElementExtractor) ExtractElementByPattern(patten string) (string, error) {
  171. if ee.Err != nil {
  172. return "", ee.Err
  173. }
  174.  
  175. var mm map[string]interface{} = ee.m
  176. var sa []interface{}
  177.  
  178. patten = strings.Replace(patten, "][", "].[", -)
  179.  
  180. for _, k := range strings.Split(patten, ".") {
  181. ki := ee.r.FindStringSubmatch(k)
  182. if len(ki) == {
  183. j, _ := strconv.Atoi(ki[])
  184. if ki[] != "" {
  185. sa = mm[ki[]].([]interface{})
  186. }
  187.  
  188. switch s := sa[j].(type) {
  189. case string:
  190. return s, nil
  191. case map[string]interface{}:
  192. mm = s
  193. case []interface{}:
  194. sa = sa[j].([]interface{})
  195. default:
  196. return fmt.Sprintf("%v", s), nil
  197. }
  198. } else {
  199. switch s := mm[k].(type) {
  200. case string:
  201. return s, nil
  202. case map[string]interface{}:
  203. mm = s
  204. default:
  205. return fmt.Sprintf("%v", s), nil
  206. }
  207. }
  208. }
  209.  
  210. ee.Err = errors.New("Pattern Error: " + patten)
  211. return "", ee.Err
  212. }
  213.  
  214. func main() {
  215. ee := NewElementExtractor(s)
  216. w := NewWeather()
  217.  
  218. w.Status, _ = ee.ExtractElementByPattern("status")
  219. w.Error_Code, _ = ee.ExtractElementByPattern("error")
  220. w.Result.Now.City, _ = ee.ExtractElementByPattern("results[0].currentCity")
  221. w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].pm25")
  222. w.Result.Future[].Date, _ = ee.ExtractElementByPattern("results[0].weather_data[2].date")
  223. w.Result.LivingIndex[].Title, _ = ee.ExtractElementByPattern("results[0].index[0].title")
  224. w.Result.Future[].Temperature, _ = ee.ExtractElementByPattern("results[0].weather_data[2].temperature")
  225. w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].test[0][1]")
  226. w.Result.Now.WindDirection, _ = ee.ExtractElementByPattern("results[0].test[1].ao")
  227. w.Result.Now.WindStrength, _ = ee.ExtractElementByPattern("results[0].test[2]")
  228.  
  229. if ee.Err != nil {
  230. fmt.Println(ee.Err)
  231. } else {
  232. fmt.Println(w)
  233. }
  234. }

运行结果:

  1. &{0 success {{郑州 xxx vfe shit} [{穿衣 } { } { } { } { } { }] [{ } { } {22 ~ 9 周六} { }]}}

[笔记]Go语言实现同一结构体适配多种消息源的更多相关文章

  1. C语言中的结构体,结构体数组

    C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...

  2. Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...

  3. 4-17疑难点 c语言之【结构体对齐】

    今天学习了结构体这一章节,了解到了结构体在分配内存的时候采取的是对齐的方式 例如: #include<stdio.h> struct test1 { int a; char b; shor ...

  4. C语言第九讲,结构体

    C语言第九讲,结构体 一丶结构体的定义 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{ 结构体所包含的变量或数组 }; 结构体是一种 ...

  5. C 语言实例 - 使用结构体(struct)

    C 语言实例 - 使用结构体(struct) C 语言实例 C 语言实例 使用结构体(struct)存储学生信息. 实例 #include <stdio.h> struct student ...

  6. Verilog缺少一个复合数据类型,如C语言中的结构体

    https://mp.weixin.qq.com/s/_9UsgUQv-MfLe8nS938cfQ Verilog中的数据类型(Data Type)是分散的,缺少一个复合数据类型:把多个wire, r ...

  7. GO学习-(13) Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有"类"的概念,也不支持"类"的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. ...

  8. 【学习笔记】【C语言】指向结构体的指针

    1.指向结构体的指针的定义 struct Student *p;  2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...

  9. C语言中的结构体

    用户自己建立自己的结构体类型 1.  定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...

随机推荐

  1. ArcGIS教程:“流向”的工作原理

    获取表面的水文特征的关键之中的一个是可以确定从栅格中的每一个像元流出的方向.这可通过流向工具来完毕. 该工具把表面作为输入,然后输出一个显示从每一个像元流出方向的栅格. 假设选择了输出下降率栅格数据选 ...

  2. 在使用add()方法添加组件到容器时,必须指定将其放置在哪个区域中

    BorderLayout是Window.Frame和Dialog的默认布局管理器,其将容器分成North.South.East.West和Center 5个区域,每个区域只能放置一个组件. 在使用ad ...

  3. hdu 5360 Hiking(优先队列+贪心)

    题目:http://acm.hdu.edu.cn/showproblem.php? pid=5360 题意:beta有n个朋友,beta要邀请他的朋友go hiking,已知每一个朋友的理想人数[L, ...

  4. inux redis 安装配置, 以及redis php扩展

    一,什么是redis redis是一个key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset ...

  5. (转)ThreadLocal

    转自:http://blog.csdn.net/lufeng20/article/details/24314381 Thread同步机制的比较 ThreadLocal和线程同步机制相比有什么优势呢?T ...

  6. 蓝桥杯 第三届C/C++预赛真题(4) 奇怪的比赛(递归)

    某电视台举办了低碳生活大奖赛.题目的计分规则相当奇怪: 每位选手需要回答10个问题(其编号为1到10),越后面越有难度.答对的,当前分数翻倍:答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错 ...

  7. CentOS中Apache虚拟主机(virtualHost)设置在/home目录下的若干问题

    在Ubuntu中安装LAMP是非常简单的意见事情.但是在CentOS中却遇到了很多问题. 首先是CentOS中必须手动配置iptables,把80端口开放出来,不然,是访问不到的,开放80端口在/et ...

  8. js 跳转的几种方法收藏

    history.go(-n) 返回上一页(n 为返回前几页) window.location.reload(); 刷新当前页面 history.go(-1);window.locatoin.reloa ...

  9. AngularJS 讲解,二 模块

    AngularJS允许我们使用angular.module()方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表. angular.mo ...

  10. 8782:乘积最大(划分dp)

    8782:乘积最大   同洛谷 P1018 乘积最大 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我 ...