golang 多级json生成 地区列表

golang map用法  https://ashitani.jp/golangtips/tips_map.html

 

* map.go

package main

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

func main() {
	var provinceList []interface{}
	var districtList []interface{}
	var province map[string]interface{}
	var m map[string]interface{}
	
	m = make(map[string]interface{})
	m["name"] = "安庆"
	m["items"] = [...]string{"大观区","怀宁县","潜山县","宿松县","太湖县","桐城市","望江县","宜秀区","迎江区","岳西县"}
	districtList = append(districtList, m)

	m = make(map[string]interface{})
	m["name"] = "蚌埠"
	m["items"] = [...]string{"龙子湖区","固镇县","怀远县","淮上区","五河县","禹会区","蚌山区"}
	districtList = append(districtList, m)

	province = make(map[string]interface{})
	province["name"] = "安徽"
	province["items"] = districtList

	provinceList = append(provinceList, province)
	
	jsonStr, err := json.Marshal(provinceList)
	if err!=nil{
		log.Fatal(err)
		return
	}
	
	fmt.Printf("%s\n",jsonStr)
}

* test: 

$ go run map.go
[{"items":[{"items":["大观区","怀宁县","潜山县","宿松县","太湖县","桐城市","望江县","宜秀区","迎江区","岳西县"],"name":"安庆"},{"items":["龙子湖区","固镇县","怀远县","淮上区","五河县","禹会区","蚌山区"],"name":"蚌埠"}],"name":"安徽"}]
 

格式化:

[{
    "items": [{
        "items": ["大观区", "怀宁县", "潜山县", "宿松县", "太湖县", "桐城市", "望江县", "宜秀区", "迎江区", "岳西县"],
        "name": "安庆"
    }, {
        "items": ["龙子湖区", "固镇县", "怀远县", "淮上区", "五河县", "禹会区", "蚌山区"],
        "name": "蚌埠"
    }],
    "name": "安徽"
}]

* 建表语句

CREATE TABLE `W_DistrictInfo` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `districtname` varchar(50) NOT NULL DEFAULT '',
  `districtcode` varchar(20) NOT NULL DEFAULT '',
  `parentid` mediumint(8) NOT NULL DEFAULT '0',
  `path` varchar(30) NOT NULL DEFAULT '',
  `level` tinyint(1) NOT NULL DEFAULT '0',
  `isvalid` tinyint(1) NOT NULL DEFAULT '1',
  `districttype` tinyint(1) NOT NULL DEFAULT '0',
  `inserttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `areacode` varchar(10) NOT NULL DEFAULT '',
  `isneedcheckmobile` tinyint(1) NOT NULL DEFAULT '0' COMMENT '该地区用户是否需要验证手机号',
  PRIMARY KEY (`id`),
  KEY `idx_districtname_path` (`districtname`,`path`),
  KEY `idx_path` (`path`),
  KEY `idx_parentid` (`parentid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

* W_DistrictInfo.sql

--

http://47.93.27.106/share/W_DistrictInfo.sql

* DistrctModel.go

package models

import (
	"fmt"
	"github.com/go-xorm/xorm"
	"time"
)

type DistrictModel struct {
	Id                int64     `xorm:"not null pk autoincr INT(11)"`
	Districtname      string    `json:"districtname" xorm:"varchar(50) not null 'districtname'"`
	Districtcode      string    `json:"districtcode" xorm:"varchar(20) not null 'districtcode'"`
	Parentid          int64     `json:"parentid" xorm:"mediumint(8) not null 'parentid'"`
	Path              string    `json:"path" xorm:"varchar(30) not null 'path'"`
	Level             int       `json:"level" xorm:"tinyint(1) not null 'level'"`
	Isvalid           int       `json:"isvalid" xorm:"tinyint(1) not null 'isvalid'"`
	Districttype      int       `json:"districttype" xorm:"tinyint(1) not null 'districttype'"`
	Inserttime        time.Time `json:"inserttime" xorm:"timestamp not null 'inserttime'"`
	Areacode          string    `json:"areacode" xorm:"varchar(10) not null 'areacode'"`
	Isneedcheckmobile int       `json:"isneedcheckmobile" xorm:"tinyint(1) not null 'isneedcheckmobile'"`
}

func (this *DistrictModel) TableName() string {
	return "W_DistrictInfo"
}

func GetValidArea() ([]DistrictModel, error) {
	var engine *xorm.Engine = nil
	engine = DbDefault()

	var list []DistrictModel
	err := engine.Where("level

* District.go

package data

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"gitlab.easytech-main.com/mingzhanghui/ginplus/log"
	"gitlab.easytech-main.com/webdev/ucenter/src/handlers"
	"gitlab.easytech-main.com/webdev/ucenter/src/models"
	"gitlab.easytech-main.com/webdev/ucenter/src/pkg/errno"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

type District struct{}

const CACHE_PATH = "./conf/providers/district.json"

// 地区数据更新
func (this *District) V1(c *gin.Context) {
	// 是否更新缓存 默认0不更新
	var update = c.DefaultQuery("update", "0")
	var list []interface{}
	var err error
	var cachePath string

	cachePath, err = this.getLatestDistrictCachePath()
	if err != nil {
		handlers.SendResponse(c, errno.ErrOpenFile, err.Error())
		return
	}
	// 没有json缓存文件, 或强制更新
	if strings.Compare(cachePath, "") == 0 || strings.Compare(update, "1") == 0 {
		list, err = this.getDistrictList()
		if err != nil {
			handlers.SendResponse(c, errno.ErrDatabase, err.Error())
			return
		}
		go this.makeCache(list)
		handlers.SendResponse(c, errno.OK, list)
		return
	}
	// --- 以下 有缓存文件 ---
	// TODO: 缓存文件过期
	// 缓存文件存在没有过期, 直接读取
	var content []byte
	content, err = file_get_contents(cachePath)
	if err != nil {
		handlers.SendResponse(c, errno.ErrOpenFile, err.Error())
		return
	}
	err = json.Unmarshal(content, &list)
	if err != nil {
		handlers.SendResponse(c, errno.ErrBind, err.Error())
		return
	}
	handlers.SendResponse(c, errno.OK, list)
}

func (this *District) getLatestDistrictCachePath() (string, error) {
	var providerDir = filepath.Dir(CACHE_PATH)
	var files sort.StringSlice
	var err error
	var path string

	files, err = filepath.Glob(providerDir + "/district*.json")
	if len(files) < 1 {
		return "", err
	}
	if err != nil {
		return "", err
	}
	sort.Strings(files)
	path = files[len(files)-1]

	return path, nil
}

func (this *District) makeCache(list []interface{}) error {
	var err error
	var jsonStr []byte
	jsonStr, err = json.Marshal(list)
	if err != nil {
		return err
	}
	var providerDir = filepath.Dir(CACHE_PATH)
	var cachePath = fmt.Sprintf("%s/district_%s.json",
		providerDir,
		time.Now().Format("20060102"))
	log.Info("District cache made: " + cachePath)

	return file_put_contents(cachePath, jsonStr)
}

func (this *District) getDistrictList() ([]interface{}, error) {
	var err error
	var list []models.DistrictModel
	var provinceList []interface{} // []models.DistrictModel
	var cityList []interface{}
	var countryList []string
	var filterCity func(model models.DistrictModel) bool
	var filterCountry func(model models.DistrictModel) bool
	var m map[string]interface{}
	var provinceMap map[string]interface{}
	var cityMap map[string]interface{}

	list, err = models.GetValidArea()
	if err != nil {
		return nil, err
	}
	provinceList = models.FilterAreaList(list, func(e models.DistrictModel) bool {
		return e.Parentid == 0
	})
	for i, province := range provinceList {
		filterCity = func(model models.DistrictModel) bool {
			m = province.(map[string]interface{})
			return model.Parentid == m["id"].(int64)
		}
		cityList = models.FilterAreaList(list, filterCity)
		provinceMap = provinceList[i].(map[string]interface{})
		provinceMap["items"] = cityList
		for j, city := range cityList {
			filterCountry = func(model models.DistrictModel) bool {
				m = city.(map[string]interface{})
				return model.Parentid == m["id"].(int64)
			}
			countryList = models.FilterCountry(list, filterCountry)
			cityMap = cityList[j].(map[string]interface{})
			cityMap["items"] = countryList
			delete(cityMap, "id")
		}
		delete(provinceMap, "id")
		// delete(provinceMap, "pid")
	}
	return provinceList, nil
}

func file_get_contents(filePath string) ([]byte, error) {
	f, err := os.Open(filePath)
	if err != nil {
		return []byte{}, err
	}
	var ba []byte
	ba, err = ioutil.ReadAll(f)
	return ba, err
}

func file_put_contents(filePath string, content []byte) error {
	return ioutil.WriteFile(filePath, content, 0644)
}

* router.go

// ...

// 地区列表
v1.GET("/district", new(data.District).V1)

// ...

 

 

你可能感兴趣的:(golang)