TopoJSON เป็นการเข้ารหัสข้อมูลทางภูมิศาสตร์ที่กระชับ และโดยทั่วไปแต่ละฟีเจอร์ในไฟล์ TopoJSON จะมีอ็อบเจกต์แอตทริบิวต์แทนที่จะเป็นชุดคีย์‑ค่าแบบแบน การส่งออกโครงสร้างนั้นเป็น CSV คือจุดที่มักจะเกิดปัญหา: เครื่องมือส่วนใหญ่จะทิ้งอ็อบเจกต์ที่ซ้อนกันหรือแปลงเป็นสตริง JSON ที่ฝังอยู่ในเซลล์เดียว คู่มือฉบับนี้แสดง วิธีแปลง TopoJSON เป็น CSV ใน C# โดยใช้ Aspose.GIS ทำให้แอตทริบิวต์แต่ละตัวสามารถเข้าถึงได้เป็นคอลัมน์ของตนเองและสามารถเขียนเรขาคณิตพร้อมกับมันในรูปแบบ Well‑Known Text ได้ตามต้องการ.
ผลลัพธ์คือชุดข้อมูล GIS แบบลำดับชั้นจะกลายเป็นตารางแบนที่ SQL Server, Power BI, pandas หรือสเปรดชีตธรรมดาสามารถใช้ได้โดยตรง โดยไม่มีชั้นการแยกวิเคราะห์ JSON ที่กำหนดเองในแอปพลิเคชันของคุณ.
ทำไมต้องแปลง TopoJSON เป็น CSV ด้วย Aspose.GIS
พิจารณา TopoJSON feature ที่มี properties มีลักษณะดังนี้:
{
"name": "North District",
"prop1": { "this": "that" }
}
ผู้เขียน CSV อย่างหยาบมีตัวเลือกที่แย่สามอย่าง: ลบ prop1, ซีเรียลไลซ์เป็น {"this":"that"} ลงในเซลล์เดียว, หรือให้ล้มเหลว ทั้งสามตัวเลือกผลักปัญหาไปข้างหลัง, ที่ซึ่งต้องมีคนต้องแยก JSON จากคอลัมน์ข้อความก่อนที่พวกเขาจะสามารถกรองหรือเข้าร่วมได้.
Aspose.GIS ใช้วิธีการที่แตกต่างกัน เมื่อไดรเวอร์ TopoJSON อ่านไฟล์ มันจะทำการโปรเจกต์อ็อบเจกต์ที่ซ้อนกันเข้าสู่สคีมาของเลเยอร์เป็นแอตทริบิวต์แบนที่ตั้งชื่อตามเส้นทางของมัน โดยเชื่อมต่อพาเรนต์และชิลด์ด้วยเครื่องหมายขีดล่าง ฟีเจอร์ข้างต้นจะแสดงเป็นสองคอลัมน์ธรรมดา:
| คอลัมน์ | ค่า |
|---|---|
name | เขตเหนือ |
prop1_this | นั้น |
เนื่องจากการทำให้แบนเกิดขึ้นในขณะอ่านข้อมูล ขั้นตอนการแปลงจึงไม่ต้องการการจัดการพิเศษใด ๆ ทั้งสิ้น สิ่งที่ชั้นเปิดเผยคือสิ่งที่ถูกเขียนลงไป ดังนั้น prop1_this จะปรากฏในไฟล์ CSV เป็นคอลัมน์ระดับแรกที่คุณสามารถเรียงลำดับ, กรองและทำการ join ได้
ข้อกำหนดเบื้องต้นสำหรับการแปลง TopoJSON เป็น CSV
- .NET 6.0 หรือใหม่กว่า, หรือ .NET Framework 4.6.2 หรือใหม่กว่า
- Aspose.GIS for .NET, ติดตั้งจาก NuGet
- ไฟล์ TopoJSON ที่มีอย่างน้อยหนึ่งอ็อบเจ็กต์แอตทริบิวต์ซ้อนกัน
ติดตั้งแพ็กเกจด้วย .NET CLI:
dotnet add package Aspose.GIS
หรือจาก Package Manager Console:
Install-Package Aspose.GIS
รายละเอียดการตั้งชื่อหนึ่งทำให้คนสับสน: แพคเกจ NuGet และแอสเซมบลีชื่อ Aspose.GIS, แต่เนมสเปซรากคือ Aspose.Gis โดยมีตัวอักษร is เป็นตัวพิมพ์เล็ก. ตัวเลือกของไดรเวอร์ CSV อยู่ใน Aspose.Gis.Formats.Csv
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
รายละเอียดผลิตภัณฑ์อยู่ใน หน้าเพจผลิตภัณฑ์ Aspose.GIS for .NET, พร้อมรายการประเภททั้งหมดใน เอกสารอ้างอิง API.
ตรวจสอบสคีมาที่ทำให้แบนก่อนที่คุณจะทำการแปลง
สิ่งที่คุณจะบรรลุ: เปิดเลเยอร์ TopoJSON และพิมพ์ชื่อแอตทริบิวต์ของมันเพื่อให้คุณทราบอย่างแน่นอนว่าคอลัมน์ใดบ้างที่จะอยู่ใน CSV
ขั้นตอนนี้คุ้มค่าที่จะทำหนึ่งครั้งกับไฟล์ตัวอย่างที่เป็นตัวแทน มันบอกชื่อคอลัมน์จริงที่ได้จากการทำให้แบน ซึ่งน่าเชื่อถือกว่าการเดาจาก JSON ดิบอย่างมาก
using System;
using Aspose.Gis;
using (VectorLayer layer = VectorLayer.Open("data/regions.topojson", Drivers.TopoJson))
{
Console.WriteLine($"Features: {layer.Count}");
foreach (FeatureAttribute attribute in layer.Attributes)
{
Console.WriteLine($" {attribute.Name} ({attribute.DataType})");
}
}
สำหรับคุณลักษณะตัวอย่างที่แสดงก่อนหน้านี้ นี้จะพิมพ์ name (String) และ prop1_this (String) วัตถุที่ซ้อนกันจะไม่ปรากฏเป็นแอตทริบิวต์แยกจากกัน ซึ่งเป็นสิ่งที่คุณต้องการอย่างแท้จริง.
แปลง TopoJSON เป็น CSV พร้อมคงคุณลักษณะที่ซ้อนกัน
สิ่งที่คุณจะทำสำเร็จ: โหลดไฟล์ TopoJSON, เขียนแอตทริบิวต์ที่แบนทั้งหมดลงในไฟล์ CSV, และอ่านผลลัพธ์กลับมาเพื่อยืนยันว่าคอลัมน์นั้นผ่านไปได้
กระบวนการแบบขั้นตอนต่อขั้นตอน
- กำหนดเส้นทางของไฟล์ TopoJSON ต้นทางและเส้นทางของไฟล์ CSV ปลายทาง.
- เปิดไฟล์ต้นทางด้วย
VectorLayer.Openและยืนยันว่ามีแอตทริบิวต์ที่แบนอยู่. - เรียกใช้เมธอด static
VectorLayer.Convertoverload พร้อมกับไดรเวอร์ต้นทางและปลายทาง. - เปิดไฟล์ CSV ใหม่ด้วย
Drivers.Csvและตรวจสอบจำนวนคอลัมน์และค่าต่าง ๆ.
ตัวอย่างต่อไปนี้จะแปลงไฟล์ TopoJSON เป็น CSV พร้อมทำให้คุณสมบัติที่ซ้อนกันแบนลงไปในระหว่างการแปลง.
using System;
using System.IO;
using Aspose.Gis;
class TopoJsonToCsv
{
static void Main()
{
string sourcePath = Path.Combine("data", "regions.topojson");
string destinationPath = Path.Combine("output", "regions.csv");
Directory.CreateDirectory("output");
// Confirm the nested property was flattened when the layer was opened.
using (VectorLayer source = VectorLayer.Open(sourcePath, Drivers.TopoJson))
{
Console.WriteLine($"Source features: {source.Count}");
Console.WriteLine($"Has prop1_this: {source.Attributes.Contains("prop1_this")}");
}
// No options are needed. The conversion writes whatever columns the
// source layer exposes, flattened attributes included.
VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv);
// Read the CSV back and verify the schema survived the round trip.
using (VectorLayer csv = VectorLayer.Open(destinationPath, Drivers.Csv))
{
Console.WriteLine($"Rows: {csv.Count}, Columns: {csv.Attributes.Count}");
if (csv.Attributes.Contains("prop1_this"))
{
Console.WriteLine($"First value: {csv[0].GetValue<string>("prop1_this")}");
}
// No WKT column was requested, so features read back without geometry.
Console.WriteLine($"Geometry empty: {csv[0].Geometry.IsEmpty}");
}
}
}
คำอธิบาย
VectorLayer.Open(string, FileDriver)เปิดไฟล์แบบอ่านอย่างเดียว.Drivers.TopoJsonคืนค่าไดรเวอร์สำหรับรูปแบบ TopoJSON.FeatureAttributeCollection.Contains(string)เป็นวิธีที่ประหยัดที่สุดในการทดสอบคอลัมน์ตามชื่อ.IndexOfให้ตำแหน่งของมันหากคุณต้องการ.VectorLayer.Convert(string, FileDriver, string, FileDriver)เป็นตัวช่วยแบบสแตติกที่สตรีมแหล่งข้อมูลไปยังรูปแบบปลายทางในหนึ่งคำสั่ง. มีการโอเวอร์โหลดที่รับConversionOptionsอีกด้วย, ใช้ในส่วนต่อไป.Feature.GetValue<T>(string)อ่านค่าคุณลักษณะที่มีประเภท. ใช้GetValueOrDefault<T>(string)เมื่อคอลัมน์อาจหายไปหรือเป็น null, เนื่องจากGetValue<T>สมมติว่ามีค่าอยู่.- การตรวจสอบสุดท้ายเป็นสิ่งที่ทำให้คนหลายคนประหลาดใจ. ไฟล์ CSV ไม่มีคอลัมน์ geometry เว้นแต่คุณจะสร้างขึ้น, ดังนั้นฟีเจอร์แต่ละรายการจะกลับมาพร้อมกับ geometry ว่าง. นั่นคือพฤติกรรมเริ่มต้น, ไม่ใช่ความล้มเหลวของการแปลง, และส่วนต่อไปจะแก้ไขมัน.
การห่อหุ้มทั้งสองชั้นด้วยบล็อก using มีความสำคัญในที่นี้: VectorLayer implements IDisposable และไฟล์ปลายทางไม่รับประกันว่าจะถูก flush และปิดจนกว่าจะถูกทำลาย.
รวมเรขาคณิตเป็น WKT โดยใช้ CsvOptions
สิ่งที่คุณจะทำสำเร็จ: สร้างไฟล์ CSV ที่บรรจุทั้งแอตทริบิวต์ที่แบนลง และ คอลัมน์ที่เก็บเรขาคณิตของแต่ละฟีเจอร์ในรูปแบบ Well-Known Text.
ขั้นตอนแบบทีละขั้น
- สร้างอินสแตนซ์
CsvOptionsและตั้งค่าColumnWktให้เป็นชื่อคอลัมน์ที่คุณเลือก - กำหนดให้กับ
ConversionOptions.DestinationDriverOptions - เรียกใช้ overload
VectorLayer.Convertที่รับตัวเลือกการแปลง - เปิดไฟล์ CSV ใหม่ด้วย
CsvOptionsเดียวกัน เพื่อให้ไดรเวอร์ทราบว่าคอลัมน์ใดจะต้องแปลงเป็นเรขาคณิต
using System;
using System.IO;
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
class TopoJsonToCsvWithGeometry
{
static void Main()
{
string sourcePath = Path.Combine("data", "regions.topojson");
string destinationPath = Path.Combine("output", "regions-wkt.csv");
Directory.CreateDirectory("output");
// Ask the CSV driver for a geometry column named "GeometryWkt".
var csvOptions = new CsvOptions
{
ColumnWkt = "GeometryWkt"
};
var conversionOptions = new ConversionOptions
{
DestinationDriverOptions = csvOptions
};
VectorLayer.Convert(
sourcePath,
Drivers.TopoJson,
destinationPath,
Drivers.Csv,
conversionOptions);
// Pass the same options when reading, or the WKT column is just text.
using (VectorLayer layer = VectorLayer.Open(destinationPath, Drivers.Csv, csvOptions))
{
foreach (Feature feature in layer)
{
string name = feature.GetValueOrDefault<string>("name");
string wkt = feature.Geometry.IsEmpty ? "(empty)" : feature.Geometry.AsText();
Console.WriteLine($"{name}: {wkt}");
}
}
}
}
คำอธิบาย
CsvOptions.ColumnWktชื่อคอลัมน์ที่เก็บเรขาคณิตของแต่ละฟีเจอร์ในรูปแบบ WKT. ค่าเริ่มต้นคือnullและการปล่อยให้เป็นnullหรือว่างเปล่าคือสาเหตุที่ตัวอย่างก่อนหน้าผลลัพธ์ไม่มีเรขาคณิตConversionOptions.DestinationDriverOptionsมีประเภทเป็นDriverOptionsซึ่งเป็นคลาสฐานสำหรับอ็อบเจ็กต์การตั้งค่าของไดรเวอร์แต่ละตัว. การส่งCsvOptionsเมื่อไดรเวอร์ปลายทางคือDrivers.Csvทำให้การตั้งคินี้ทำงาน; การส่งตัวเลือกประเภทผิดสำหรับไดรเวอร์จะทำให้เกิดArgumentException- อินสแตนซ์
CsvOptionsเดียวกันถูกใช้ซ้ำในด้านการอ่าน. หากไม่มีมัน ไดรเวอร์ CSV จะไม่มีเหตุผลที่จะถือGeometryWktเป็นอย่างอื่นนอกจากคอลัมน์สตริงทั่วไป IGeometry.AsText()คืนค่าการแสดงผล ISO WKT ดังนั้นผลลัพธ์ที่พิมพ์ออกมาจะตรงกับที่เขียนลงไฟล์
สมมาตรคือจุดสำคัญ: คอลัมน์แอตทริบิวต์ทำงานเหมือนกันไม่ว่าจะมีเรขาคณิตหรือไม่ก็ตาม ดังนั้นคุณสามารถเปิดหรือปิดคอลัมน์ WKT ได้โดยไม่ต้องแตะต้องส่วนอื่นของ pipeline ของคุณ.
แปลงพิกัดระหว่างการแปลง
หากระบบที่ใช้รับข้อมูลคาดหวังระบบพิกัดเฉพาะ ให้ขอข้อมูลนั้นเป็นส่วนหนึ่งของการแปลงแทนที่จะทำการประมวลผลต่อหลังจาก CSV แล้ว ConversionOptions จะบรรจุการอ้างอิงเชิงพื้นที่พร้อมกับตัวเลือกของไดรเวอร์:
var conversionOptions = new ConversionOptions
{
DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" },
DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84
};
VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv, conversionOptions);
ไม่ใช่ไดรเวอร์ปลายทางทั้งหมดที่รองรับทุกระบบอ้างอิงเชิงพื้นที่. เรียก Drivers.Csv.SupportsSpatialReferenceSystem(...) ก่อนหากระบบเป้าหมายสามารถกำหนดค่าได้ในเวลารันไทม์ และกลับไปใช้วัตถุตัวเลือกเป็น null เมื่อไม่รองรับ.
แปลงโฟลเดอร์ของไฟล์ TopoJSON เป็นชุด
API มีลักษณะเดียวกันสำหรับไฟล์หนึ่งไฟล์และไฟล์หนึ่งพันไฟล์ กฎเดียวที่ควรจำเมื่อทำการประมวลผลแบบขนานคือแต่ละ worker ต้องมี layer และ options objects ของตนเอง
using System;
using System.IO;
using System.Threading.Tasks;
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
static void ConvertFolder(string inputFolder, string outputFolder)
{
Directory.CreateDirectory(outputFolder);
var files = Directory.GetFiles(inputFolder, "*.topojson");
Parallel.ForEach(files, file =>
{
string destination = Path.Combine(
outputFolder,
Path.GetFileNameWithoutExtension(file) + ".csv");
// Fresh options per iteration: nothing is shared across threads.
var options = new ConversionOptions
{
DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" }
};
try
{
VectorLayer.Convert(file, Drivers.TopoJson, destination, Drivers.Csv, options);
}
catch (GisException ex)
{
Console.Error.WriteLine($"Skipped {Path.GetFileName(file)}: {ex.Message}");
}
});
}
การดักจับ GisException ต่อไฟล์แทนที่จะทำรอบลูปทั้งหมดหมายความว่าไฟล์ TopoJSON ที่ผิดรูปแบบหนึ่งไฟล์จะบันทึกคำเตือนแทนที่จะยกเลิกการทำงานของชุด
รับใบอนุญาตฟรี
Aspose.GIS ทำงานในโหมดประเมินผลจนกว่าจะมีการใช้ใบอนุญาต ขอรับใบอนุญาตชั่วคราวฟรีจาก หน้าใบอนุญาตชั่วคราวของ Aspose และใช้มันหนึ่งครั้งเมื่อตัวแอปพลิเคชันเริ่มทำงาน ก่อนการเรียก Aspose.GIS ใด ๆ:
var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");
Free Additional Resources
สรุป
การแปลง TopoJSON ที่มีคุณสมบัติเชิงซ้อนเป็น CSV ใน .NET มีขั้นตอนหลักเพียงหนึ่งที่เป็นประโยชน์: Aspose.GIS จะทำให้วัตถุแอตทริบิวต์ที่ซ้อนกันแบนเป็นคอลัมน์ที่มีชื่อ เช่น prop1_this ขณะอ่านเลเยอร์ ดังนั้น VectorLayer.Convert ไม่จำเป็นต้องมีตรรกะกำหนดเองเพื่อรักษาข้อมูลเหล่านั้น เพิ่ม CsvOptions.ColumnWkt เมื่อระบบ downstream ต้องการเรขาคณิต, เพิ่ม DestinationSpatialReferenceSystem เมื่อระบบต้องการการฉายภาพเฉพาะ, และวนลูปการเรียกเดียวกันเมื่อคุณต้องการประมวลผลโฟลเดอร์ ผลลัพธ์คือ ตารางแบนพร้อมสำหรับการวิเคราะห์ที่สร้างขึ้นด้วยไม่กี่บรรทัดของ C# โดยไม่ต้องมีชั้นการแปลง JSON ของคุณเองเพื่อดูแลรักษา.
FAQs
Can Aspose.GIS flatten nested JSON objects when converting to CSV? ใช่. TopoJSON driver เปิดเผยอ็อบเจ็กต์แอตทริบิวต์ที่ซ้อนกันเป็นคอลัมน์แยกเมื่อเลเยอร์ถูกเปิด, โดยเชื่อมชื่อพาเรนต์และชิลด์ด้วยเครื่องหมายขีดล่าง, ดังนั้นการทำให้แบนได้ถูกดำเนินการแล้วก่อนการแปลงทำงาน.
ฉันต้องเขียนโค้ดกำหนดเองเพื่อจัดการกับคุณสมบัติที่ซ้อนกันหรือไม่? ไม่.
VectorLayer.Convertจะเขียนคอลัมน์ใด ๆ ที่เลเยอร์ต้นทางเปิดเผย, ดังนั้นคุณสมบัติที่ซ้อนกันจึงไม่ต้องการโค้ดการแยกวิเคราะห์เพิ่มเติมของคุณเอง.ฉันจะใส่ข้อมูลเรขาคณิตในผลลัพธ์ CSV ได้อย่างไร? สร้างอินสแตนซ์ของ
CsvOptionsตั้งค่าคุณสมบัติColumnWktให้เป็นชื่อคอลัมน์ที่คุณต้องการ กำหนดให้กับConversionOptions.DestinationDriverOptionsแล้วส่งผ่านไปยังVectorLayer.Convert.ทำไม geometry ถึงว่างเปล่าเมื่อฉันอ่าน CSV กลับ? CSV ไม่มีคอลัมน์ geometry เว้นแต่คุณจะขอให้มี. ตั้งค่า
ColumnWktบนCsvOptionsที่คุณส่งทั้งในขณะเขียนและอ่าน, มิฉะนั้นไดรเวอร์จะไม่มีคอลัมน์ที่สามารถสร้าง geometry ได้.ข้อยกเว้นใดที่ฉันควรจัดการระหว่างการแปลง? ข้อยกเว้นที่ระบุไว้คือ
ArgumentNullExceptionสำหรับเส้นทางที่เป็น null,ArgumentExceptionเมื่อวัตถุตัวเลือกไม่ตรงกับไดรเวอร์,GisExceptionเมื่อไม่สามารถอ่านฟีเจอร์จากไฟล์, และIOExceptionสำหรับความล้มเหลวของ I/O พื้นฐาน.ฉันสามารถแปลงชุดไฟล์ TopoJSON ได้พร้อมกันหรือไม่? ใช่. วนลูปผ่านรายการไฟล์และเรียก
VectorLayer.Convertสำหรับแต่ละไฟล์ หากคุณทำการประมวลผลแบบขนาน ให้แต่ละ worker มีVectorLayerและอินสแตนซ์ของ options ของตนเอง แทนการแชร์หนึ่งอันระหว่างเธรดการแปลงทำให้ระบบพิกัดเปลี่ยนแปลงหรือไม่? โดยค่าเริ่มต้นไม่มีการเปลี่ยนแปลง. เพื่อทำการรีโปรเจกต์ระหว่างการแปลง ให้ตั้งค่า
ConversionOptions.DestinationSpatialReferenceSystemเป็นระบบเป้าหมายก่อนเรียกConvert.
