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:

KolumnVärde
nameNorra distriktet
prop1_thisdet

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

  1. Definiera källans TopoJSON‑sökväg och destinations‑CSV‑sökvägen.
  2. Öppna källan med VectorLayer.Open och bekräfta att det plattade attributet finns.
  3. Anropa den statiska VectorLayer.Convert‑överladdningen med käll‑ och destinationsdrivrutinerna.
  4. Öppna CSV‑filen igen med Drivers.Csv och 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.TopoJson returnerar drivrutinen för TopoJSON-formatet.
  • FeatureAttributeCollection.Contains(string) är det billigaste sättet att testa om en kolumn finns med namn. IndexOf ger 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 tar ConversionOptions, som används i nästa avsnitt.
  • Feature.GetValue<T>(string) läser ett typat attributvärde. Använd GetValueOrDefault<T>(string) när en kolumn kan saknas eller vara null, eftersom GetValue<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

  1. Skapa en CsvOptions-instans och sätt ColumnWkt till det valda kolumnnamnet.
  2. Tilldela den till ConversionOptions.DestinationDriverOptions.
  3. Anropa VectorLayer.Convert-överlagringen som accepterar konverteringsalternativ.
  4. Öppna CSV-filen igen med samma CsvOptions så 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.ColumnWkt namnger kolumnen som innehåller varje funktions geometri i WKT‑format. Den har standardvärdet null, 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 typen DriverOptions, bas‑klassen för varje drivrutins inställningsobjekt. Att skicka en CsvOptions där destinationsdrivrutinen är Drivers.Csv är vad som får inställningen att träda i kraft; att skicka alternativ av fel typ för en drivrutin kastar ett ArgumentException.
  • Samma CsvOptions‑instans återanvänds på lässidan. Utan den har CSV‑drivrutinen ingen anledning att behandla GeometryWkt som 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

  1. 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.

  2. Behöver jag skriva anpassad kod för att hantera nästlade egenskaper?
    Nej. VectorLayer.Convert skriver alla kolumner som källagret exponerar, så nästlade egenskaper kräver ingen extra parsingskod från dig.

  3. Hur kan jag inkludera geometri i CSV-utdata? Skapa en CsvOptions-instans, sätt dess ColumnWkt-egenskap till det kolumnnamn du vill ha, tilldela den till ConversionOptions.DestinationDriverOptions och skicka den till VectorLayer.Convert.

  4. 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 ColumnWkt på CsvOptions som du skickar både vid skrivning och vid läsning, annars har drivrutinen ingen kolumn att bygga en geometri från.

  5. Vilka undantag bör jag hantera under konverteringen?
    De dokumenterade är ArgumentNullException för en null‑sökväg, ArgumentException när ett alternativobjekt inte matchar drivrutinen, GisException när en funktion inte kan läsas från filen, och IOException för underliggande I/O‑fel.

  6. Kan jag konvertera en batch av TopoJSON-filer på en gång? Ja. Loopa över fillistan och anropa VectorLayer.Convert för varje fil. Om du parallelliserar loopen, ge varje arbetare sin egen VectorLayer och options‑instanser snarare än att dela en över trådar.

  7. Ändrar konverteringen koordinatsystemet? Inte som standard. För att reprojicera under konverteringen, sätt ConversionOptions.DestinationSpatialReferenceSystem till målsystemet innan du anropar Convert.

Läs mer