TopoJSON är en kompakt kodning av geografiska data, och det är vanligt att varje funktion i en TopoJSON‑fil bär ett attributobjekt snarare än en platt uppsättning nyckel‑värde‑par. Att exportera den strukturen till CSV är där saker vanligtvis går fel: de flesta verktyg antingen släpper det inbäddade objektet eller dumpar det som en JSON‑sträng som hamnar i en enda cell. Denna guide visar hur man konverterar TopoJSON till CSV i C# med hjälp av Aspose.GIS, och behåller varje attribut adresserbart som en egen kolumn och valfritt skriver geometrin bredvid som Well‑Known Text.
Vinsten är att ett hierarkiskt GIS‑dataset blir en platt tabell som SQL Server, Power BI, pandas eller ett vanligt kalkylblad kan konsumera direkt, utan ett specialbyggt JSON‑parsningslager i din applikation.
Varför konvertera TopoJSON till CSV med Aspose.GIS
Tänk på ett TopoJSON-element vars egenskaper ser ut så här:
{
"name": "North District",
"prop1": { "this": "that" }
}
En naiv CSV‑skrivare har tre dåliga alternativ: släppa prop1, serialisera den som {"this":"that"} i en cell, eller misslyckas. Alla tre skjuter problemet vidare, där någon måste återparsa JSON från en textkolumn innan de kan filtrera eller göra en join på den.
Aspose.GIS tar ett annat tillvägagångssätt. När TopoJSON‑drivrutinen läser filen projicerar den det nästlade objektet i lager‑schemat som ett platt attribut namngivet efter dess sökväg, där förälder och barn förenas med ett understreck. Funktionen ovan exponeras som två vanliga kolumner:
| Kolumn | Värde |
|---|---|
name | Norra distriktet |
prop1_this | det |
Eftersom plattningen sker vid läsningstid, kräver konverteringssteget ingen särskild hantering alls. Vad lagret exponerar är vad som skrivs, så prop1_this hamnar i CSV-filen som en förstklassig kolumn som du kan sortera, filtrera och ansluta till.
Förutsättningar för TopoJSON till CSV-konvertering
- .NET 6.0 eller senare, eller .NET Framework 4.6.2 eller senare
- Aspose.GIS for .NET, installerad från NuGet
- En TopoJSON‑fil som innehåller minst ett nästlat attributobjekt
Installera paketet med .NET CLI:
dotnet add package Aspose.GIS
Eller från Package Manager Console:
Install-Package Aspose.GIS
En namngivningsdetalj får folk att snubbla: NuGet‑paketet och samlingen heter Aspose.GIS, men rot‑namnutrymmet är Aspose.Gis med ett litet is. CSV‑drivrutinsalternativen finns i Aspose.Gis.Formats.Csv.
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
Produktdetaljer finns på Aspose.GIS for .NET produktsida, med den fullständiga typlistan i API-referens.
Inspektera det plattade schemat innan du konverterar
Vad du kommer att uppnå: Öppna TopoJSON‑lagret och skriv ut dess attributnamn så att du exakt vet vilka kolumner CSV‑filen kommer att innehålla.
Detta steg är värt att göra en gång mot en representativ fil. Det visar dig de faktiska kolumnnamnen som genereras genom plattning, vilket är mycket mer pålitligt än att gissa dem från den råa JSON‑en.
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 det exempel på funktionen som visades tidigare skriver detta ut name (String) och prop1_this (String). Det nästlade objektet visas aldrig som ett eget attribut, vilket är exakt vad du vill ha.
Konvertera TopoJSON till CSV samtidigt som du bevarar nästlade attribut
Vad du kommer att uppnå: Ladda en TopoJSON‑fil, skriv varje plattlagd attribut till en CSV‑fil och läs tillbaka resultatet för att bekräfta att kolumnen gick igenom.
Steg-för-steg-process
- Definiera källans TopoJSON‑sökväg och destinations‑CSV‑sökvägen.
- Öppna källan med
VectorLayer.Openoch bekräfta att det plattade attributet finns. - Anropa den statiska
VectorLayer.Convert‑överladdningen med käll‑ och destinationsdrivrutinerna. - Öppna CSV‑filen igen med
Drivers.Csvoch kontrollera kolumnantalet och värdena.
Följande exempel konverterar en TopoJSON‑fil till CSV och plattar till nästlade egenskaper på vägen.
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}");
}
}
}
Förklaring
VectorLayer.Open(string, FileDriver)öppnar filen skrivskyddad.Drivers.TopoJsonreturnerar drivrutinen för TopoJSON-formatet.FeatureAttributeCollection.Contains(string)är det billigaste sättet att testa om en kolumn finns med namn.IndexOfger dig dess position om du behöver den.VectorLayer.Convert(string, FileDriver, string, FileDriver)är en statisk hjälpfunktion som strömmar källan till destinationsformatet i ett anrop. Det finns också en överlagring som tarConversionOptions, som används i nästa avsnitt.Feature.GetValue<T>(string)läser ett typat attributvärde. AnvändGetValueOrDefault<T>(string)när en kolumn kan saknas eller vara null, eftersomGetValue<T>förutsätter att värdet finns.- Den sista kontrollen är den som överraskar folk. En CSV-fil har ingen geometrikolumn om du inte skapar en, så varje feature kommer tillbaka med en tom geometri. Det är standardbeteendet, inte ett konverteringsfel, och nästa avsnitt åtgärdar det.
Att omsluta båda lagren i using‑block är viktigt här: VectorLayer implementerar IDisposable, och destinationsfilen är inte garanterad att bli spolförd och stängd förrän den har frigörts.
Inkludera geometri som WKT med CsvOptions
Vad du kommer att uppnå: Skapa en CSV som innehåller både de plattade attributen och en kolumn som innehåller varje funktions geometri som Well-Known Text.
Steg-för-steg process
- Skapa en
CsvOptions-instans och sättColumnWkttill det valda kolumnnamnet. - Tilldela den till
ConversionOptions.DestinationDriverOptions. - Anropa
VectorLayer.Convert-överlagringen som accepterar konverteringsalternativ. - Öppna CSV-filen igen med samma
CsvOptionsså att drivrutinen vet vilken kolumn som ska tolkas som geometri.
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}");
}
}
}
}
Förklaring
CsvOptions.ColumnWktnamnger kolumnen som innehåller varje funktions geometri i WKT‑format. Den har standardvärdetnull, och att låta den vara null eller tom är exakt orsaken till att det tidigare exemplet inte skapade någon geometri.ConversionOptions.DestinationDriverOptionsär av typenDriverOptions, bas‑klassen för varje drivrutins inställningsobjekt. Att skicka enCsvOptionsdär destinationsdrivrutinen ärDrivers.Csvär vad som får inställningen att träda i kraft; att skicka alternativ av fel typ för en drivrutin kastar ettArgumentException.- Samma
CsvOptions‑instans återanvänds på lässidan. Utan den har CSV‑drivrutinen ingen anledning att behandlaGeometryWktsom något annat än en vanlig strängkolumn. IGeometry.AsText()returnerar ISO WKT‑representationen, så den utskrivna outputen matchar det som skrevs till filen.
Symmetrin är poängen: attributkolumnerna beter sig identiskt oavsett om geometri är inkluderad eller inte, så du kan slå på och av WKT‑kolumnen utan att röra resten av din pipeline.
Omprojicera under konvertering
Om det konsumerande systemet förväntar sig ett specifikt koordinatsystem, be om det som en del av konverteringen snarare än efterbehandling av CSV. ConversionOptions innehåller en rumslig referens tillsammans med drivrutinsalternativen:
var conversionOptions = new ConversionOptions
{
DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" },
DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84
};
VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv, conversionOptions);
Inte alla destinationsdrivrutiner stöder alla rumsliga referenssystem. Anropa Drivers.Csv.SupportsSpatialReferenceSystem(...) först om målssystemet kan konfigureras vid körning, och falla tillbaka till ett null‑alternativobjekt när det inte stöds.
Batchkonvertera en mapp med TopoJSON-filer
API:et är identiskt för en fil och för tusen. Den enda regeln som är värd att komma ihåg när du parallelliserar är att varje arbetare behöver sina egna lager- och alternativobjekt.
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}");
}
});
}
Att fånga GisException per fil istället för runt hela loopen betyder att en felaktig TopoJSON‑fil loggar en varning i stället för att avbryta batchen.
Få en gratis licens
Aspose.GIS körs i utvärderingsläge tills en licens har tillämpats. Begär en gratis tillfällig licens från Aspose temporära licenssida och tillämpa den en gång vid applikationsstart, innan något annat Aspose.GIS‑anrop:
var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");
Gratis ytterligare resurser
Slutsats
Att konvertera TopoJSON med nästlade egenskaper till CSV i .NET reduceras till ett användbart beteende: Aspose.GIS plattar till nästlade attributobjekt till namngivna kolumner såsom prop1_this medan lagret läses, så VectorLayer.Convert kräver ingen anpassad logik för att bevara dem. Lägg till CsvOptions.ColumnWkt när det nedströms systemet behöver geometri, lägg till DestinationSpatialReferenceSystem när det behöver en specifik projektion, och upprepa samma anrop när du behöver bearbeta en mapp. Resultatet är en platt, analysklar tabell som produceras av ett fåtal rader C#, utan att du själv måste underhålla ett JSON‑parsningslager.
Vanliga frågor
Kan Aspose.GIS platta till nästlade JSON-objekt när man konverterar till CSV? Ja. TopoJSON-drivrutinen exponerar ett nästlat attributobjekt som separata kolumner när lagret öppnas, och förenar föräldra- och barnnamn med ett understreck, så plattningen är redan utförd innan konverteringen körs.
Behöver jag skriva anpassad kod för att hantera nästlade egenskaper?
Nej.VectorLayer.Convertskriver alla kolumner som källagret exponerar, så nästlade egenskaper kräver ingen extra parsingskod från dig.Hur kan jag inkludera geometri i CSV-utdata? Skapa en
CsvOptions-instans, sätt dessColumnWkt-egenskap till det kolumnnamn du vill ha, tilldela den tillConversionOptions.DestinationDriverOptionsoch skicka den tillVectorLayer.Convert.Varför är geometrin tom när jag läser tillbaka min CSV? En CSV har ingen geometrikolumn om du inte begär en. Ställ in
ColumnWktpåCsvOptionssom du skickar både vid skrivning och vid läsning, annars har drivrutinen ingen kolumn att bygga en geometri från.Vilka undantag bör jag hantera under konverteringen?
De dokumenterade ärArgumentNullExceptionför en null‑sökväg,ArgumentExceptionnär ett alternativobjekt inte matchar drivrutinen,GisExceptionnär en funktion inte kan läsas från filen, ochIOExceptionför underliggande I/O‑fel.Kan jag konvertera en batch av TopoJSON-filer på en gång? Ja. Loopa över fillistan och anropa
VectorLayer.Convertför varje fil. Om du parallelliserar loopen, ge varje arbetare sin egenVectorLayeroch options‑instanser snarare än att dela en över trådar.Ändrar konverteringen koordinatsystemet? Inte som standard. För att reprojicera under konverteringen, sätt
ConversionOptions.DestinationSpatialReferenceSystemtill målsystemet innan du anroparConvert.
