之前的一篇文章里介紹了geojson的標(biāo)準(zhǔn)格式,這里介紹一下用C#的Newtonsoft.Json庫對一個geojson文件進(jìn)行解析,因為Python的json庫解析json還是非常容易的,用json.load或json.loads就可以讀入json數(shù)據(jù)然后按照字典或列表的方式進(jìn)行定位和更改其中的內(nèi)容,因為最近一個 項目需要用C#進(jìn)行解析,這里做一個記錄。
下載與安裝Newtonsoft.Json
首先在官網(wǎng)下載Newtonsoft.Json。官網(wǎng)上號稱:
Popular high-performance JSON framework for .NET
當(dāng)然確實還是很好用的,提供的接口還是挺友好的,開始入手可能有一些小困難。這個庫的功能主要有3大塊,分別為序列化json(將文本保存的json解析為可查詢的json)、反序列化json和用LINQ對json進(jìn)行查詢。
在官網(wǎng)上可以點擊Download下載壓縮文件然后在自己的工程的解決方案管理器里添加引用,找到Newtonsoft.Json.dll文件然后引用。還有一個更快捷的方式是使用程序包管理器控制臺進(jìn)行安裝,過程如下圖:

先打開程序包管理器控制臺,然后輸入Install-Package Newtonsoft.json 進(jìn)行安裝。
安裝好后在項目里記得添上using Newtonsoft.Json;這條語句。
這個庫提供的數(shù)據(jù)類型有JObject、JProperty以及最基本的JToken。
讀入json數(shù)據(jù)
下面是讀入json并序列化到一個JObject對象的過程
StreamReader sr = new StreamReader(inputFile, Encoding.UTF8);
JObject o = JObject.Parse(sr.ReadToEnd());
如果輸入文件inputFile不是標(biāo)準(zhǔn)的json格式可能會引發(fā)JsonReaderException異常。
索引對應(yīng)數(shù)據(jù)
例如下面的geojson數(shù)據(jù):
{
"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可以對應(yīng)各種類型的數(shù)據(jù),并且保存著原來json的結(jié)構(gòu),可以在向下索引或者回溯到父節(jié)點。而JToken jfts = o["features"]已知內(nèi)容是一個數(shù)組,可以用List<JToken> jlst = jfts.ToList();對里面的元素進(jìn)行枚舉,
List<JToken> jlst = jfts.ToList();
for (int i = 0; i < j jlst.Count; i++){
//do sth
}
對于json的在大括號里的鍵值對(一般稱為字典格式)數(shù)據(jù),可以通過類似 o["features"] 的方式,將鍵放在中括號里進(jìn)行索引,可以多級索引并保存為數(shù)值類型或者文本類型(需要一個隱式轉(zhuǎn)換的語句)而不限于JToken進(jìn)行保存,例如:string jtw = (string)jlst[i]["geometry"]["type"];,如果想要提取鍵怎么辦呢?JToken沒有獲取鍵的接口,這個我摸索了一段時間,可以通過JProperty類型來解決,JProperty 有Name接口可以獲取相應(yīng)的Name;
JToken gprop = jlst[i]["properties"];
JProperty jpeo = (JProperty)gprop.ElementAt(0);
string usingStr=jpeo.Name;
geojson數(shù)據(jù)寫入csv
下面是一個提取geojson的點數(shù)據(jù)到csv和根據(jù)csv寫一個geojson文件的小示例,包含了從0開始寫一個geojson文件的過程。
/// <summary>
/// geojson轉(zhuǎn)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 轉(zhuǎn)換完成";//邏輯上不是,但為了不覆蓋catch的內(nèi)容,寫在了這里
}
catch (Exception exp) {
infoLabel.Text = exp.Message;
}
}else { //
}
}
csvWter.Close();
}
/// <summary>
/// csv轉(zhuǎn)geojson的點數(shù)據(jù)
/// </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文件為空,請確認(rèn)輸入文件后重試";
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 轉(zhuǎn)geojson完成!";
}
catch( Exception expt) {
infoLabel.Text = expt.Message;
}
}
Newtonsoft.Json可以很優(yōu)秀地處理json格式的數(shù)據(jù),也可以將其他類型的數(shù)據(jù)(例如kml)解析為json,本文主要講了這個庫處理geojson數(shù)據(jù)的一些方式。
如果您有其他解析需求沒能在本文中找到答案,可以在其官方文檔查看相應(yīng)方法或函數(shù)的使用。