TopoJSON — це компактне кодування географічних даних, і зазвичай кожна функція у файлі TopoJSON містить об’єкт атрибутів, а не простий набір пар ключ‑значення. Експорт цієї структури у CSV — це те місце, де зазвичай виникають проблеми: більшість інструментів або відкидає вкладений об’єкт, або виводить його назад як рядок JSON, вставлений в одну клітинку. У цьому посібнику показано, як конвертувати TopoJSON у CSV на C# за допомогою Aspose.GIS, зберігаючи кожен атрибут доступним у власному стовпці та за потреби записуючи геометрію поруч у вигляді Well‑Known Text.

Перевага полягає в тому, що ієрархічний GIS‑набір даних перетворюється на плоску таблицю, яку SQL Server, Power BI, pandas або проста електронна таблиця можуть безпосередньо використовувати, без спеціального шару розбору JSON у вашому застосунку.

Чому конвертувати TopoJSON у CSV за допомогою Aspose.GIS

Розгляньте TopoJSON‑об’єкт, властивості якого виглядають так:

{
  "name": "North District",
  "prop1": { "this": "that" }
}

Наївний CSV‑записувач має три погані варіанти: відкинути prop1, серіалізувати його як {"this":"that"} в одну клітинку або завершити роботу з помилкою. Усі три передають проблему вниз по потоку, де хтось має повторно розпарсити JSON з текстового стовпця, перш ніж зможе фільтрувати або приєднувати його.

Aspose.GIS застосовує інший підхід. Коли драйвер TopoJSON читає файл, він проєктує вкладений об’єкт у схему шару як плоский атрибут, названий за його шляхом, об’єднуючи батьківський і дочірній елементи підкресленням. Наведена вище функція представлена як два звичайні стовпці:

СтовпецьЗначення
nameПівнічний район
prop1_thisте

Оскільки сплющування відбувається під час читання, крок перетворення не потребує жодного спеціального оброблення. Те, що шар експонує, саме і записується, тому prop1_this потрапляє у CSV як колонка першого класу, яку можна сортувати, фільтрувати та приєднувати.

Вимоги до конвертації TopoJSON у CSV

  • .NET 6.0 або новіший, або .NET Framework 4.6.2 або новіший
  • Aspose.GIS for .NET, встановлений з NuGet
  • Файл TopoJSON, що містить принаймні один вкладений об’єкт атрибуту

Встановіть пакет за допомогою .NET CLI:

dotnet add package Aspose.GIS

Або з консолі диспетчера пакетів:

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. Викличте статичне перевантаження VectorLayer.Convert з драйверами джерела та призначення.
  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‑файлі немає колонки геометрії, якщо ви її не створите, тому кожна функція повертається з порожньою геометрією. Це поведінка за замовчуванням, а не помилка конвертації, і наступний розділ виправляє це.

Обгортання обох шарів у блоки using має значення тут: VectorLayer реалізує IDisposable, і файл призначення не гарантовано буде очищений і закритий, доки не буде вивільнений.

Включення геометрії у форматі WKT за допомогою CsvOptions

Що ви досягнете: Створіть CSV, який містить як сплощені атрибути і стовпець, що містить геометрію кожного об’єкта у форматі Well-Known Text.

Покроковий процес

  1. Створіть екземпляр CsvOptions і встановіть ColumnWkt у назву вибраного стовпця.
  2. Призначте його ConversionOptions.DestinationDriverOptions.
  3. Викличте перевантаження 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, не торкаючись решти вашого конвеєра.

Перепроектування під час конвертації

Якщо система‑споживач очікує певну систему координат, запитайте її як частину конвертації, а не під час пост‑обробки 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 ідентичний для одного файлу і для тисячі. Єдине правило, яке варто пам’ятати під час паралелізації, — кожен воркер потребує власних об’єктів layer і options.

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");

Безкоштовні додаткові ресурси

Висновок

Перетворення TopoJSON з вкладеними властивостями у CSV у .NET зводиться до однієї корисної поведінки: Aspose.GIS розгортає вкладені об’єкти атрибутів у названі стовпці, наприклад prop1_this, під час читання шару, тому VectorLayer.Convert не потребує спеціальної логіки для їх збереження. Додайте CsvOptions.ColumnWkt, коли нижчестояща система потребує геометрії, додайте DestinationSpatialReferenceSystem, коли потрібна конкретна проекція, і повторюйте той самий виклик у циклі, коли потрібно обробити папку. Результатом є плоска, готова до аналізу таблиця, створена кількома рядками C#, без необхідності підтримувати власний шар парсингу JSON.

Часті запитання

  1. Чи може Aspose.GIS сплющувати вкладені об’єкти JSON під час конвертації у CSV?
    Так. Драйвер TopoJSON представляє вкладений об’єкт атрибутів як окремі стовпці, коли шар відкривається, об’єднуючи імена батька та дитини підкресленням, тому сплющування вже виконано до запуску конвертації.

  2. Чи потрібно писати власний код для обробки вкладених властивостей? Ні. VectorLayer.Convert записує всі стовпці, які надає вихідний шар, тому вкладені властивості не потребують додаткового коду парсингу з вашого боку.

  3. Як я можу включити геометрію у CSV‑вивід? Створіть екземпляр CsvOptions, встановіть його властивість ColumnWkt у назву стовпця, яку ви хочете, призначте його ConversionOptions.DestinationDriverOptions і передайте його в VectorLayer.Convert.

  4. Чому геометрія порожня, коли я читаю свій CSV назад? CSV не має стовпця геометрії, якщо ви явно не запитаєте його. Встановіть ColumnWkt у CsvOptions, які ви передаєте як під час запису, так і під час читання, інакше драйвер не матиме стовпця, з якого можна створити геометрію.

  5. Які виключення слід обробляти під час перетворення? Документовані виключення: ArgumentNullException для null шляху, ArgumentException коли об’єкт параметрів не відповідає драйверу, GisException коли функція не може бути прочитана з файлу, та IOException для помилок нижчого рівня вводу/виводу.

  6. Чи можу я конвертувати пакет TopoJSON файлів одночасно? Так. Пройдіться по списку файлів і викличте VectorLayer.Convert для кожного файлу. Якщо ви паралелізуєте цикл, дайте кожному робітнику його власний екземпляр VectorLayer та параметрів, а не діліться одним між потоками.

  7. Чи змінює конвертація систему координат? За замовчуванням — ні. Щоб виконати репроекцію під час конвертації, встановіть ConversionOptions.DestinationSpatialReferenceSystem у цільову систему перед викликом Convert.

Читати далі