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, และอ่านผลลัพธ์กลับมาเพื่อยืนยันว่าคอลัมน์นั้นผ่านไปได้

กระบวนการแบบขั้นตอนต่อขั้นตอน

  1. กำหนดเส้นทางของไฟล์ TopoJSON ต้นทางและเส้นทางของไฟล์ CSV ปลายทาง.
  2. เปิดไฟล์ต้นทางด้วย VectorLayer.Open และยืนยันว่ามีแอตทริบิวต์ที่แบนอยู่.
  3. เรียกใช้เมธอด static VectorLayer.Convert overload พร้อมกับไดรเวอร์ต้นทางและปลายทาง.
  4. เปิดไฟล์ 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.

ขั้นตอนแบบทีละขั้น

  1. สร้างอินสแตนซ์ CsvOptions และตั้งค่า ColumnWkt ให้เป็นชื่อคอลัมน์ที่คุณเลือก
  2. กำหนดให้กับ ConversionOptions.DestinationDriverOptions
  3. เรียกใช้ overload VectorLayer.Convert ที่รับตัวเลือกการแปลง
  4. เปิดไฟล์ 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

  1. Can Aspose.GIS flatten nested JSON objects when converting to CSV? ใช่. TopoJSON driver เปิดเผยอ็อบเจ็กต์แอตทริบิวต์ที่ซ้อนกันเป็นคอลัมน์แยกเมื่อเลเยอร์ถูกเปิด, โดยเชื่อมชื่อพาเรนต์และชิลด์ด้วยเครื่องหมายขีดล่าง, ดังนั้นการทำให้แบนได้ถูกดำเนินการแล้วก่อนการแปลงทำงาน.

  2. ฉันต้องเขียนโค้ดกำหนดเองเพื่อจัดการกับคุณสมบัติที่ซ้อนกันหรือไม่? ไม่. VectorLayer.Convert จะเขียนคอลัมน์ใด ๆ ที่เลเยอร์ต้นทางเปิดเผย, ดังนั้นคุณสมบัติที่ซ้อนกันจึงไม่ต้องการโค้ดการแยกวิเคราะห์เพิ่มเติมของคุณเอง.

  3. ฉันจะใส่ข้อมูลเรขาคณิตในผลลัพธ์ CSV ได้อย่างไร? สร้างอินสแตนซ์ของ CsvOptions ตั้งค่าคุณสมบัติ ColumnWkt ให้เป็นชื่อคอลัมน์ที่คุณต้องการ กำหนดให้กับ ConversionOptions.DestinationDriverOptions แล้วส่งผ่านไปยัง VectorLayer.Convert.

  4. ทำไม geometry ถึงว่างเปล่าเมื่อฉันอ่าน CSV กลับ? CSV ไม่มีคอลัมน์ geometry เว้นแต่คุณจะขอให้มี. ตั้งค่า ColumnWkt บน CsvOptions ที่คุณส่งทั้งในขณะเขียนและอ่าน, มิฉะนั้นไดรเวอร์จะไม่มีคอลัมน์ที่สามารถสร้าง geometry ได้.

  5. ข้อยกเว้นใดที่ฉันควรจัดการระหว่างการแปลง? ข้อยกเว้นที่ระบุไว้คือ ArgumentNullException สำหรับเส้นทางที่เป็น null, ArgumentException เมื่อวัตถุตัวเลือกไม่ตรงกับไดรเวอร์, GisException เมื่อไม่สามารถอ่านฟีเจอร์จากไฟล์, และ IOException สำหรับความล้มเหลวของ I/O พื้นฐาน.

  6. ฉันสามารถแปลงชุดไฟล์ TopoJSON ได้พร้อมกันหรือไม่? ใช่. วนลูปผ่านรายการไฟล์และเรียก VectorLayer.Convert สำหรับแต่ละไฟล์ หากคุณทำการประมวลผลแบบขนาน ให้แต่ละ worker มี VectorLayer และอินสแตนซ์ของ options ของตนเอง แทนการแชร์หนึ่งอันระหว่างเธรด

  7. การแปลงทำให้ระบบพิกัดเปลี่ยนแปลงหรือไม่? โดยค่าเริ่มต้นไม่มีการเปลี่ยนแปลง. เพื่อทำการรีโปรเจกต์ระหว่างการแปลง ให้ตั้งค่า ConversionOptions.DestinationSpatialReferenceSystem เป็นระบบเป้าหมายก่อนเรียก Convert.

อ่านต่อ