TopoJSON ist eine kompakte Kodierung geografischer Daten, und es ist üblich, dass jedes Feature in einer TopoJSON‑Datei ein Attributobjekt trägt, anstatt einer flachen Menge von Schlüssel‑Wert‑Paaren. Das Exportieren dieser Struktur nach CSV ist dort, wo normalerweise Probleme auftreten: Die meisten Werkzeuge lassen entweder das verschachtelte Objekt weg oder geben es als JSON‑String in einer einzelnen Zelle aus. Dieser Leitfaden zeigt wie man TopoJSON in CSV in C# konvertiert mit Aspose.GIS, wobei jedes Attribut als eigene Spalte adressierbar bleibt und optional die Geometrie daneben als Well‑Known Text geschrieben wird.
Der Nutzen besteht darin, dass ein hierarchischer GIS‑Datensatz zu einer flachen Tabelle wird, die SQL Server, Power BI, pandas oder eine einfache Tabellenkalkulation direkt verarbeiten kann, ohne dass in Ihrer Anwendung eine maßgeschneiderte JSON‑Parsing‑Schicht erforderlich ist.
Warum TopoJSON in CSV mit Aspose.GIS konvertieren
Betrachten Sie ein TopoJSON-Feature, dessen Eigenschaften wie folgt aussehen:
{
"name": "North District",
"prop1": { "this": "that" }
}
Ein naiver CSV‑Schreiber hat drei schlechte Optionen: prop1 weglassen, es als {"this":"that"} in einer Zelle serialisieren oder fehlschlagen. Alle drei schieben das Problem nach unten, wo jemand JSON aus einer Textspalte neu parsen muss, bevor er filtern oder joinen kann.
Aspose.GIS verfolgt einen anderen Ansatz. Wenn der TopoJSON‑Treiber die Datei liest, projiziert er das verschachtelte Objekt in das Ebenenschema als flaches Attribut, das nach seinem Pfad benannt ist, wobei Eltern‑ und Kind‑Elemente mit einem Unterstrich verbunden werden. Das oben gezeigte Feature wird als zwei gewöhnliche Spalten dargestellt:
| Spalte | Wert |
|---|---|
name | Nordbezirk |
prop1_this | das |
Da das Flattening zur Lesezeit erfolgt, benötigt der Konvertierungsschritt keinerlei spezielle Behandlung. Was immer die Ebene bereitstellt, wird geschrieben, sodass prop1_this in die CSV als erstklassige Spalte gelangt, die Sie sortieren, filtern und verbinden können.
Voraussetzungen für die Konvertierung von TopoJSON zu CSV
- .NET 6.0 oder höher, oder .NET Framework 4.6.2 oder höher
- Aspose.GIS for .NET, installiert über NuGet
- Eine TopoJSON‑Datei, die mindestens ein verschachteltes Attributobjekt enthält
Installieren Sie das Paket mit der .NET CLI:
dotnet add package Aspose.GIS
Oder über die Package Manager Console:
Install-Package Aspose.GIS
Ein Namensdetail verwirrt die Leute: Das NuGet‑Paket und die Assembly heißen Aspose.GIS, aber der Root‑Namespace ist Aspose.Gis mit einem kleinen is. Die CSV‑Treiberoptionen befinden sich in Aspose.Gis.Formats.Csv.
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
Produktdetails finden Sie auf der Aspose.GIS for .NET Produktseite, mit der vollständigen Typenauflistung in der API‑Referenz.
Untersuchen Sie das abgeflachte Schema, bevor Sie konvertieren
Was Sie erreichen werden: Öffnen Sie die TopoJSON‑Schicht und geben Sie deren Attributnamen aus, damit Sie genau wissen, welche Spalten die CSV enthalten wird.
Dieser Schritt lohnt sich, einmal an einer repräsentativen Datei durchzuführen. Er zeigt Ihnen die tatsächlichen Spaltennamen, die durch das Flattening erzeugt werden, was weitaus zuverlässiger ist, als sie aus dem rohen JSON zu erraten.
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})");
}
}
Für das zuvor gezeigte Beispiel-Feature gibt dies name (String) und prop1_this (String) aus. Das verschachtelte Objekt erscheint niemals als eigenständiges Attribut, was genau das ist, was Sie wollen.
TopoJSON in CSV konvertieren und verschachtelte Attribute beibehalten
Was Sie erreichen werden: Laden Sie eine TopoJSON-Datei, schreiben Sie jedes abgeflachte Attribut in eine CSV-Datei und lesen Sie das Ergebnis zurück, um zu bestätigen, dass die Spalte durchgekommen ist.
Schritt-für-Schritt-Prozess
- Definieren Sie den Quell‑TopoJSON-Pfad und den Ziel‑CSV-Pfad.
- Öffnen Sie die Quelle mit
VectorLayer.Openund bestätigen Sie, dass das abgeflachte Attribut existiert. - Rufen Sie die statische Überladung
VectorLayer.Convertmit den Quell‑ und Ziel‑Treibern auf. - Öffnen Sie die CSV erneut mit
Drivers.Csvund prüfen Sie die Spaltenanzahl und die Werte.
Das folgende Beispiel konvertiert eine TopoJSON‑Datei in CSV und flacht dabei verschachtelte Eigenschaften ab.
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}");
}
}
}
Erklärung
VectorLayer.Open(string, FileDriver)öffnet die Datei schreibgeschützt.Drivers.TopoJsongibt den Treiber für das TopoJSON‑Format zurück.FeatureAttributeCollection.Contains(string)ist die günstigste Methode, um nach einer Spalte anhand ihres Namens zu prüfen.IndexOfliefert ihre Position, falls Sie diese benötigen.VectorLayer.Convert(string, FileDriver, string, FileDriver)ist ein statischer Helfer, der die Quelle in einem Aufruf in das Zielformat streamt. Es gibt auch eine Überladung, dieConversionOptionsakzeptiert und im nächsten Abschnitt verwendet wird.Feature.GetValue<T>(string)liest einen typisierten Attributwert. Verwenden SieGetValueOrDefault<T>(string), wenn eine Spalte fehlen oder null sein kann, daGetValue<T>davon ausgeht, dass der Wert vorhanden ist.- Die letzte Prüfung ist die, die die Leute überrascht. Eine CSV‑Datei hat keine Geometriespalte, es sei denn, Sie erstellen eine, sodass jedes Feature mit einer leeren Geometrie zurückkommt. Das ist das Standardverhalten, kein Konvertierungsfehler, und der nächste Abschnitt behebt das.
Das Einwickeln beider Ebenen in using‑Blöcke ist hier wichtig: VectorLayer implementiert IDisposable und die Zieldatei wird erst nach dem Entsorgen garantiert geleert und geschlossen.
Geometrie als WKT mit CsvOptions einbinden
Was Sie erreichen werden: Erzeugen Sie eine CSV, die sowohl die abgeflachten Attribute und eine Spalte enthält, die die Geometrie jedes Features als Well‑Known Text hält.
Schritt-für-Schritt-Prozess
- Erstellen Sie eine
CsvOptions‑Instanz und setzen SieColumnWktauf den von Ihnen gewählten Spaltennamen. - Weisen Sie sie
ConversionOptions.DestinationDriverOptionszu. - Rufen Sie die Überladung
VectorLayer.Convertauf, die Konvertierungsoptionen akzeptiert. - Öffnen Sie die CSV erneut mit denselben
CsvOptions, damit der Treiber weiß, welche Spalte als Geometrie zu interpretieren ist.
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}");
}
}
}
}
Erklärung
CsvOptions.ColumnWktbenennt die Spalte, die die Geometrie jedes Features in WKT‑Form enthält. Der Standardwert istnull, und das Belassen vonnulloder leer ist genau der Grund, warum das vorherige Beispiel keine Geometrie erzeugte.ConversionOptions.DestinationDriverOptionsist vom TypDriverOptions, der Basisklasse für jedes Treiber‑Einstellungsobjekt. Das Übergeben einesCsvOptions, wenn der Ziel‑TreiberDrivers.Csvist, bewirkt, dass die Einstellung wirksam wird; das Übergeben von Optionen des falschen Typs für einen Treiber löst eineArgumentExceptionaus.- Die gleiche
CsvOptions‑Instanz wird auf der Lese‑Seite wiederverwendet. Ohne sie hat der CSV‑Treiber keinen Grund,GeometryWktals etwas anderes als eine weitere String‑Spalte zu behandeln. IGeometry.AsText()gibt die ISO‑WKT‑Darstellung zurück, sodass die ausgegebene Ausgabe mit dem im Dateisystem geschriebenen Inhalt übereinstimmt.
Die Symmetrie ist der Punkt: Die Attributspalten verhalten sich identisch, egal ob Geometrie enthalten ist oder nicht, sodass Sie die WKT‑Spalte ein‑ und ausschalten können, ohne den Rest Ihrer Pipeline zu berühren.
Neu projizieren während der Konvertierung
Wenn das empfangende System ein bestimmtes Koordinatensystem erwartet, fragen Sie danach im Rahmen der Konvertierung, anstatt die CSV nachträglich zu verarbeiten. ConversionOptions enthält einen räumlichen Bezug zusammen mit den Treiberoptionen:
var conversionOptions = new ConversionOptions
{
DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" },
DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84
};
VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv, conversionOptions);
Nicht jeder Zieltreiber unterstützt jedes räumliche Referenzsystem. Rufen Sie zuerst Drivers.Csv.SupportsSpatialReferenceSystem(...) auf, wenn das Zielsystem zur Laufzeit konfigurierbar ist, und greifen Sie auf ein Null‑Optionen‑Objekt zurück, wenn es nicht unterstützt wird.
Stapelkonvertierung eines Ordners mit TopoJSON-Dateien
Die API ist für eine Datei und für tausend identisch. Die einzige Regel, die man sich beim Parallelisieren merken sollte, ist, dass jeder Worker seine eigenen Layer‑ und Optionsobjekte benötigt.
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}");
}
});
}
Das Abfangen von GisException pro Datei anstatt um die gesamte Schleife bedeutet, dass eine fehlerhafte TopoJSON‑Datei eine Warnung protokolliert, anstatt den Batch abzubrechen.
Kostenlose Lizenz erhalten
Aspose.GIS läuft im Evaluierungsmodus, bis eine Lizenz angewendet wird. Fordern Sie eine kostenlose temporäre Lizenz von der Aspose temporären Lizenzseite an und wenden Sie sie einmal beim Anwendungsstart an, bevor irgendein anderer Aspose.GIS‑Aufruf erfolgt:
var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");
Kostenlose zusätzliche Ressourcen
Fazit
Das Konvertieren von TopoJSON mit verschachtelten Eigenschaften zu CSV in .NET reduziert sich auf ein nützliches Verhalten: Aspose.GIS flacht verschachtelte Attributobjekte in benannte Spalten wie prop1_this ab, während die Ebene gelesen wird, sodass VectorLayer.Convert keine benutzerdefinierte Logik zum Beibehalten benötigt. Fügen Sie CsvOptions.ColumnWkt hinzu, wenn das nachgelagerte System Geometrie benötigt, fügen Sie DestinationSpatialReferenceSystem hinzu, wenn es eine bestimmte Projektion benötigt, und wiederholen Sie denselben Aufruf, wenn Sie einen Ordner verarbeiten müssen. Das Ergebnis ist eine flache, analysebereite Tabelle, die mit wenigen Zeilen C# erzeugt wird, ohne dass Sie eine eigene JSON‑Parsing‑Schicht pflegen müssen.
FAQs
Kann Aspose.GIS verschachtelte JSON-Objekte beim Konvertieren in CSV abflachen? Ja. Der TopoJSON‑Treiber stellt ein verschachteltes Attributobjekt als separate Spalten bereit, wenn die Ebene geöffnet wird, wobei Eltern‑ und Kind‑Namen mit einem Unterstrich verbunden werden, sodass das Abflachen bereits erfolgt, bevor die Konvertierung ausgeführt wird.
Muss ich benutzerdefinierten Code schreiben, um verschachtelte Eigenschaften zu behandeln? Nein.
VectorLayer.Convertschreibt alle Spalten, die die Quellschicht bereitstellt, sodass verschachtelte Eigenschaften keinen zusätzlichen Parsing‑Code von Ihrer Seite benötigen.Wie kann ich Geometrie in die CSV‑Ausgabe einbinden? Erstellen Sie eine
CsvOptions‑Instanz, setzen Sie derenColumnWkt‑Eigenschaft auf den gewünschten Spaltennamen, weisen Sie sieConversionOptions.DestinationDriverOptionszu und übergeben Sie sie anVectorLayer.Convert.Warum ist die Geometrie leer, wenn ich meine CSV wieder einlese? Eine CSV hat keine Geometriespalte, es sei denn, Sie fordern eine an. Setzen Sie
ColumnWktin denCsvOptions, die Sie sowohl beim Schreiben als auch beim Lesen übergeben, andernfalls hat der Treiber keine Spalte, aus der er eine Geometrie erstellen kann.Welche Ausnahmen sollten beim Konvertieren behandelt werden? Die dokumentierten Ausnahmen sind
ArgumentNullExceptionfür einen null-Pfad,ArgumentExceptionwenn ein Optionsobjekt nicht zum Treiber passt,GisExceptionwenn ein Feature nicht aus der Datei gelesen werden kann, undIOExceptionfür zugrunde liegende I/O-Fehler.Kann ich eine Charge von TopoJSON-Dateien auf einmal konvertieren? Ja. Durchlaufen Sie die Dateiliste und rufen Sie
VectorLayer.Convertfür jede Datei auf. Wenn Sie die Schleife parallelisieren, geben Sie jedem Worker seine eigenenVectorLayer- und Options-Instanzen, anstatt eine über Threads zu teilen.Ändert die Konvertierung das Koordinatensystem? Nicht standardmäßig. Um während der Konvertierung neu zu projizieren, setzen Sie
ConversionOptions.DestinationSpatialReferenceSystemauf das Zielsystem, bevor SieConvertaufrufen.
