zoukankan      html  css  js  c++  java
  • [笔记]Go语言实现同一结构体适配多种消息源

    问题:

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

    代码如下:

    package main
    
    import (
      "encoding/json"
      "errors"
      "fmt"
      "regexp"
      "strconv"
      "strings"
    )
    
    var s string = `
    {
        "error": 0, 
        "status": "success", 
        "date": "2015-03-26", 
        "results": [
            {
                "test": [
                    [
                        "fuck", 
                        "shit"
                    ], 
                    {
                        "ao": "xxx"
                    }, 
                    "vfe"
                ], 
                "currentCity": "郑州", 
                "pm25": "95", 
                "index": [
                    {
                        "title": "穿衣", 
                        "zs": "较冷", 
                        "tipt": "穿衣指数", 
                        "des": "建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。"
                    }, 
                    {
                        "title": "洗车", 
                        "zs": "不宜", 
                        "tipt": "洗车指数", 
                        "des": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
                    }, 
                    {
                        "title": "旅游", 
                        "zs": "适宜", 
                        "tipt": "旅游指数", 
                        "des": "温度适宜,又有较弱降水和微风作伴,会给您的旅行带来意想不到的景象,适宜旅游,可不要错过机会呦!"
                    }, 
                    {
                        "title": "感冒", 
                        "zs": "少发", 
                        "tipt": "感冒指数", 
                        "des": "各项气象条件适宜,无明显降温过程,发生感冒机率较低。"
                    }, 
                    {
                        "title": "运动", 
                        "zs": "较不宜", 
                        "tipt": "运动指数", 
                        "des": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意保暖并携带雨具。"
                    }, 
                    {
                        "title": "紫外线强度", 
                        "zs": "最弱", 
                        "tipt": "紫外线强度指数", 
                        "des": "属弱紫外线辐射天气,无需特别防护。若长期在户外,建议涂擦SPF在8-12之间的防晒护肤品。"
                    }
                ], 
                "weather_data": [
                    {
                        "date": "周四 03月26日 (实时:12℃)", 
                        "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/zhenyu.png", 
                        "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png", 
                        "weather": "阵雨转多云", 
                        "wind": "微风", 
                        "temperature": "12 ~ 4℃"
                    }, 
                    {
                        "date": "周五", 
                        "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png", 
                        "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png", 
                        "weather": "", 
                        "wind": "微风", 
                        "temperature": "16 ~ 8℃"
                    }, 
                    {
                        "date": "周六", 
                        "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png", 
                        "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png", 
                        "weather": "晴转多云", 
                        "wind": "微风", 
                        "temperature": "22 ~ 9℃"
                    }, 
                    {
                        "date": "周日", 
                        "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png", 
                        "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png", 
                        "weather": "", 
                        "wind": "微风", 
                        "temperature": "25 ~ 11℃"
                    }
                ]
            }
        ]
    }
    `
    
    // 天气
    type Weather struct {
      Error_Code string `json:"error_code"` //错误码  0没有错误
      Status     string `json:"status"`     // 状态描述, success 成功
      Result     Result `json:"result"`     // 天气状况
    }
    
    // 天气结果
    type Result struct {
      Now         Real
      LivingIndex []Indicate `json:"living_index"` //生活指数
      Future      []ForeCast `json:"future"`       //未来几天的预报,包括当天
    }
    
    // 实时报告
    type Real struct {
      City          string `json:"city"`           // 城市
      Temperature   string `json:"temperature"`    // 当前温度
      WindDirection string `json:"wind_direction"` // 风向
      WindStrength  string `json:"wind_strength"`  // 风强度
      Humidity      string `json:"humidity"`       // 湿度
      PM25          string `json:"pm25"`           // PM2.5
    }
    
    // 预报
    type ForeCast struct {
      Temperature string `json:"temperature"` // 温度范围
      Weather     string `json:"weather"`     // 天气  (晴,多云,阴转多云)
      Wind        string `json:"wind"`        // 风向和强度
      Week        string `json:"week"`        // 星期几
      Date        string `json:"date"`        // 日期
    }
    
    type Indicate struct {
      Title       string `json:"titile"` // 指数标题
      Status      string `json:"status"` //指数状态 (适宜,不宜)
      Description string `json:"desc"`   //描述信息
    }
    
    func NewWeather() *Weather {
      return NewWeatherWithNum(6, 4)
    }
    
    func NewWeatherWithNum(livingIndexNum, forecastNum int) *Weather {
      w := &Weather{}
      w.Result.LivingIndex = make([]Indicate, livingIndexNum)
      w.Result.Future = make([]ForeCast, forecastNum)
      return w
    }
    
    type ElementExtractor struct {
      Err error
      m   map[string]interface{}
      r   *regexp.Regexp
    }
    
    func NewElementExtractor(jsonString string) *ElementExtractor {
      ee := &ElementExtractor{r: regexp.MustCompile(`(.*)[(d+)]+`)}
      ee.Err = json.Unmarshal([]byte(jsonString), &ee.m)
      return ee
    }
    
    func (ee *ElementExtractor) ExtractElementByPattern(patten string) (string, error) {
      if ee.Err != nil {
        return "", ee.Err
      }
    
      var mm map[string]interface{} = ee.m
      var sa []interface{}
    
      patten = strings.Replace(patten, "][", "].[", -1)
    
      for _, k := range strings.Split(patten, ".") {
        ki := ee.r.FindStringSubmatch(k)
        if len(ki) == 3 {
          j, _ := strconv.Atoi(ki[2])
          if ki[1] != "" {
            sa = mm[ki[1]].([]interface{})
          }
    
          switch s := sa[j].(type) {
          case string:
            return s, nil
          case map[string]interface{}:
            mm = s
          case []interface{}:
            sa = sa[j].([]interface{})
          default:
            return fmt.Sprintf("%v", s), nil
          }
        } else {
          switch s := mm[k].(type) {
          case string:
            return s, nil
          case map[string]interface{}:
            mm = s
          default:
            return fmt.Sprintf("%v", s), nil
          }
        }
      }
    
      ee.Err = errors.New("Pattern Error: " + patten)
      return "", ee.Err
    }
    
    func main() {
      ee := NewElementExtractor(s)
      w := NewWeather()
    
      w.Status, _ = ee.ExtractElementByPattern("status")
      w.Error_Code, _ = ee.ExtractElementByPattern("error")
      w.Result.Now.City, _ = ee.ExtractElementByPattern("results[0].currentCity")
      w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].pm25")
      w.Result.Future[2].Date, _ = ee.ExtractElementByPattern("results[0].weather_data[2].date")
      w.Result.LivingIndex[0].Title, _ = ee.ExtractElementByPattern("results[0].index[0].title")
      w.Result.Future[2].Temperature, _ = ee.ExtractElementByPattern("results[0].weather_data[2].temperature")
      w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].test[0][1]")
      w.Result.Now.WindDirection, _ = ee.ExtractElementByPattern("results[0].test[1].ao")
      w.Result.Now.WindStrength, _ = ee.ExtractElementByPattern("results[0].test[2]")
    
      if ee.Err != nil {
        fmt.Println(ee.Err)
      } else {
        fmt.Println(w)
      }
    }

    运行结果:

    &{0 success {{郑州  xxx vfe  shit} [{穿衣  } {  } {  } {  } {  } {  }] [{    } {    } {22 ~ 9℃    周六} {    }]}}
  • 相关阅读:
    大数据揭秘华尔街如何从金融危机中赚钱
    大数据揭秘华尔街如何从金融危机中赚钱
    CDA考试 ▏2017 CDA L1备考资源习题详解-统计基础部分
    CDA考试 ▏2017 CDA L1备考资源习题详解-统计基础部分
    同步大数据发展与大数据法制,方能形成一个良性循环
    同步大数据发展与大数据法制,方能形成一个良性循环
    Solr在Linux中的安装
    NOSQL中的redis缓存数据库
    Context initialization failed
    Caused by: java.sql.SQLException: Field 'category_id' doesn't have a default value
  • 原文地址:https://www.cnblogs.com/journeyonmyway/p/4390801.html
Copyright © 2011-2022 走看看