C#解析GEOJSON数据

之前的一篇文章里介绍了geojson的标准格式,这里介绍一下用C#的Newtonsoft.Json库对一个geojson文件进行解析,因为Python的json库解析json还是非常容易的,用json.load或json.loads就可以读入json数据然后按照字典或列表的方式进行定位和更改其中的内容,因为最近一个 项目需要用C#进行解析,这里做一个记录。

下载与安装Newtonsoft.Json

首先在官网下载Newtonsoft.Json。官网上号称:

Popular high-performance JSON framework for .NET

当然确实还是很好用的,提供的接口还是挺友好的,开始入手可能有一些小困难。这个库的功能主要有3大块,分别为序列化json(将文本保存的json解析为可查询的json)、反序列化json和用LINQ对json进行查询。

在官网上可以点击Download下载压缩文件然后在自己的工程的解决方案管理器里添加引用,找到Newtonsoft.Json.dll文件然后引用。还有一个更快捷的方式是使用程序包管理器控制台进行安装,过程如下图:

Newtonsoft.Json的安装

先打开程序包管理器控制台,然后输入Install-Package Newtonsoft.json 进行安装。

安装好后在项目里记得添上using Newtonsoft.Json;这条语句。
这个库提供的数据类型有JObject、JProperty以及最基本的JToken。

读入json数据

下面是读入json并序列化到一个JObject对象的过程

StreamReader sr = new StreamReader(inputFile, Encoding.UTF8);
JObject o = JObject.Parse(sr.ReadToEnd());

如果输入文件inputFile不是标准的json格式可能会引发JsonReaderException异常。

索引对应数据

例如下面的geojson数据:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {"NAME": "hanzghou poi", "id": 1, "prov": " zhejiang"},
      "geometry": {
        "type": "Point",
        "coordinates": [
          120.07850646972656,
          30.304428412161137
        ]
      }
    }
  ]
}
该数据的效果

我们用前面的两句代码读入后,可以用JToken jprop=o["type"]索引到文本FeatureCollection,JToken可以对应各种类型的数据,并且保存着原来json的结构,可以在向下索引或者回溯到父节点。而JToken jfts = o["features"]已知内容是一个数组,可以用List<JToken> jlst = jfts.ToList();对里面的元素进行枚举,

List<JToken> jlst = jfts.ToList();
for (int i = 0; i < j jlst.Count; i++){
    //do sth
}

对于json的在大括号里的键值对(一般称为字典格式)数据,可以通过类似 o["features"] 的方式,将键放在中括号里进行索引,可以多级索引并保存为数值类型或者文本类型(需要一个隐式转换的语句)而不限于JToken进行保存,例如:string jtw = (string)jlst[i]["geometry"]["type"];,如果想要提取键怎么办呢?JToken没有获取键的接口,这个我摸索了一段时间,可以通过JProperty类型来解决,JProperty 有Name接口可以获取相应的Name;

JToken gprop = jlst[i]["properties"];
JProperty jpeo = (JProperty)gprop.ElementAt(0);
string usingStr=jpeo.Name;

geojson数据写入csv

下面是一个提取geojson的点数据到csv和根据csv写一个geojson文件的小示例,包含了从0开始写一个geojson文件的过程。

        /// <summary>
        /// geojson转csv,只对点要素有效
        /// </summary>
        private void geojsonToCsvPoi () {
            //其他要素不管,如果没有点要素,生成为空
            StreamReader sr = new StreamReader(inputFile, Encoding.UTF8);
            JObject o = JObject.Parse(sr.ReadToEnd());

            JToken jfts = o["features"];

            List<JToken> jlst = jfts.ToList<JToken>();
            int jlen = jlst.Count;

            StreamWriter csvWter = new StreamWriter(outputFile);
            for (int i = 0; i < jlen; i++) {
                string jt1 = (string)jlst[i]["geometry"]["type"];
                if (jt1 == "Point") {
                    try {
                        Array poiArr = jlst[i]["geometry"]["coordinates"].ToArray();
                        csvWter.WriteLine(coordPoint(poiArr));
                        infoLabel.Text = "geojson to csv 转换完成";//逻辑上不是,但为了不覆盖catch的内容,写在了这里
                    }
                    catch (Exception exp) {
                        infoLabel.Text = exp.Message;
                    }
                }else { //
                }
            }
            csvWter.Close();
            
        }

        /// <summary>
        /// csv转geojson的点数据
        /// </summary>
        private void csvPoiToGeojson () {
            try {
                StreamReader csvRder = new StreamReader(inputFile,Encoding.UTF8);
                string csvall = csvRder.ReadToEnd();//读入csv文件
                string[] csvlst = csvall.Split('\n');
                List<JObject> jfeslst = new List<JObject>();
                for (int j = 0; j < csvlst.Length; j++) {
                    if (csvlst[j] == "" && j == 0) {
                        infoLabel.Text = "输入csv文件为空,请确认输入文件后重试";
                        return; //如果是空文件
                    }
                    if (csvlst[j] != "") {//排除空行
                        double[] dlst = stringPoiToDList(csvlst[j]);
                        if (dlst.Length == 5 && dlst[0] == 0d)
                            return;
                        JProperty jcoord = new JProperty("coordinates",dlst);
                        JProperty jtpoi = new JProperty("type", "Point");

                        JProperty jgomtry =new JProperty("geometry", new JObject(jtpoi, jcoord));
                        JProperty jprots = new JProperty("properties",new JObject());
                        JObject jtfea = new JObject(new JProperty("type", "Feature"),jprots,jgomtry);
                        jfeslst.Add(jtfea);
                    }
                }
                JProperty jfs = new JProperty("features", jfeslst);

                JObject jcsv = new JObject(new JProperty("type", "FeatureCollection"), jfs);
                File.WriteAllText(outputFile, jcsv.ToString());
                infoLabel.Text = "csv 转geojson完成!";
            }
            catch( Exception expt) {
                infoLabel.Text = expt.Message;
            }
        }


Newtonsoft.Json可以很优秀地处理json格式的数据,也可以将其他类型的数据(例如kml)解析为json,本文主要讲了这个库处理geojson数据的一些方式。
如果您有其他解析需求没能在本文中找到答案,可以在其官方文档查看相应方法或函数的使用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容