TopoJSON est un encodage compact des données géographiques, et il est courant que chaque entité dans un fichier TopoJSON porte un objet d’attributs plutôt qu’un ensemble plat de paires clé‑valeur. Exporter cette structure vers le CSV est l’endroit où les choses tournent souvent mal : la plupart des outils suppriment l’objet imbriqué ou le renvoient sous forme de chaîne JSON insérée dans une seule cellule. Ce guide montre comment convertir TopoJSON en CSV en C# en utilisant Aspose.GIS, en conservant chaque attribut adressable comme sa propre colonne et en écrivant éventuellement la géométrie à côté sous forme de texte Well‑Known.

Le résultat est qu’un jeu de données GIS hiérarchique devient une table plate que SQL Server, Power BI, pandas ou une simple feuille de calcul peuvent consommer directement, sans couche d’analyse JSON personnalisée dans votre application.

Pourquoi convertir TopoJSON en CSV avec Aspose.GIS

Considérez une fonction TopoJSON dont les propriétés ressemblent à ceci :

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

Un écrivain CSV naïf a trois mauvaises options : supprimer prop1, le sérialiser sous forme de {"this":"that"} dans une seule cellule, ou échouer. Les trois repoussent le problème en aval, où quelqu’un doit re‑analyser le JSON d’une colonne texte avant de pouvoir filtrer ou joindre sur celle‑ci.

Aspose.GIS adopte une approche différente. Lorsque le pilote TopoJSON lit le fichier, il projette l’objet imbriqué dans le schéma de la couche sous forme d’un attribut plat nommé d’après son chemin, en joignant le parent et l’enfant avec un soulignement. La fonctionnalité ci‑dessus est exposée sous forme de deux colonnes ordinaires :

ColonneValeur
nameDistrict Nord
prop1_thiscela

Parce que l’aplatissement se produit au moment de la lecture, l’étape de conversion ne nécessite aucun traitement spécial. Tout ce que la couche expose est ce qui est écrit, de sorte que prop1_this atterrit dans le CSV en tant que colonne de première classe que vous pouvez trier, filtrer et joindre.

Prérequis de la conversion TopoJSON en CSV

  • .NET 6.0 ou version ultérieure, ou .NET Framework 4.6.2 ou version ultérieure
  • Aspose.GIS for .NET, installé depuis NuGet
  • Un fichier TopoJSON contenant au moins un objet d’attribut imbriqué

Installez le package avec le .NET CLI:

dotnet add package Aspose.GIS

Ou depuis la console du gestionnaire de packages :

Install-Package Aspose.GIS

Un détail de nommage surprend les gens : le package NuGet et l’assembly s’appellent Aspose.GIS, mais l’espace de noms racine est Aspose.Gis avec un is en minuscule. Les options du pilote CSV se trouvent dans Aspose.Gis.Formats.Csv.

using Aspose.Gis;
using Aspose.Gis.Formats.Csv;

Les détails du produit se trouvent sur la page produit Aspose.GIS for .NET, avec la liste complète des types dans la référence API.

Inspectez le schéma aplati avant de le convertir

Ce que vous accomplirez : Ouvrez la couche TopoJSON et imprimez ses noms d’attributs afin de savoir exactement quelles colonnes le CSV contiendra.

Cette étape vaut la peine d’être effectuée une fois sur un fichier représentatif. Elle vous indique les vrais noms de colonnes générés par l’aplatissement, ce qui est beaucoup plus fiable que de les deviner à partir du JSON brut.

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

Pour la fonctionnalité d’exemple présentée précédemment, cela affiche name (String) et prop1_this (String). L’objet imbriqué n’apparaît jamais comme un attribut à part entière, ce qui est exactement ce que vous souhaitez.

Convertir TopoJSON en CSV tout en préservant les attributs imbriqués

Ce que vous accomplirez : Charger un fichier TopoJSON, écrire chaque attribut aplati dans un fichier CSV, puis lire le résultat pour confirmer que la colonne a bien été conservée.

Processus étape par étape

  1. Définissez le chemin TopoJSON source et le chemin CSV de destination.
  2. Ouvrez la source avec VectorLayer.Open et confirmez que l’attribut aplati existe.
  3. Appelez la surcharge statique VectorLayer.Convert avec les pilotes source et de destination.
  4. Rouvrez le CSV avec Drivers.Csv et vérifiez le nombre de colonnes et les valeurs.

L’exemple suivant convertit un fichier TopoJSON en CSV, en aplatissant les propriétés imbriquées en cours de route.

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

Explication

  • VectorLayer.Open(string, FileDriver) ouvre le fichier en lecture seule. Drivers.TopoJson renvoie le pilote pour le format TopoJSON.
  • FeatureAttributeCollection.Contains(string) est la façon la plus économique de tester la présence d’une colonne par son nom. IndexOf vous donne sa position si vous en avez besoin.
  • VectorLayer.Convert(string, FileDriver, string, FileDriver) est un helper statique qui transmet la source vers le format de destination en un seul appel. Il existe également une surcharge acceptant ConversionOptions, utilisée dans la section suivante.
  • Feature.GetValue<T>(string) lit une valeur d’attribut typée. Utilisez GetValueOrDefault<T>(string) lorsqu’une colonne peut être manquante ou nulle, puisque GetValue<T> suppose que la valeur est présente.
  • Le dernier contrôle est celui qui surprend les gens. Un fichier CSV n’a pas de colonne de géométrie sauf si vous en créez une, ainsi chaque entité revient avec une géométrie vide. C’est le comportement par défaut, pas un échec de conversion, et la section suivante le corrige.

Envelopper les deux couches dans des blocs using est important ici : VectorLayer implémente IDisposable, et le fichier de destination n’est pas garanti d’être vidé et fermé tant qu’il n’est pas libéré.

Inclure la géométrie au format WKT à l’aide de CsvOptions

Ce que vous accomplirez : Produisez un CSV qui contient à la fois les attributs aplatis et une colonne contenant la géométrie de chaque entité au format Well-Known Text.

Processus étape par étape

  1. Créez une instance de CsvOptions et définissez ColumnWkt sur le nom de colonne choisi.
  2. Assignez‑la à ConversionOptions.DestinationDriverOptions.
  3. Appelez la surcharge VectorLayer.Convert qui accepte les options de conversion.
  4. Rouvrez le CSV avec le même CsvOptions afin que le pilote sache quelle colonne analyser comme géométrie.
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}");
            }
        }
    }
}

Explication

  • CsvOptions.ColumnWkt nomme la colonne qui contient la géométrie de chaque entité sous forme WKT. Elle vaut null par défaut, et la laisser à null ou vide explique exactement pourquoi l’exemple précédent n’a produit aucune géométrie.
  • ConversionOptions.DestinationDriverOptions est typé comme DriverOptions, la classe de base pour l’objet de paramètres de chaque pilote. Fournir un CsvOptions lorsque le pilote de destination est Drivers.Csv permet au paramètre de prendre effet ; fournir des options d’un type incorrect pour un pilote déclenche une ArgumentException.
  • La même instance de CsvOptions est réutilisée du côté lecture. Sans elle, le pilote CSV n’a aucune raison de traiter GeometryWkt comme autre chose qu’une colonne de chaîne de caractères.
  • IGeometry.AsText() renvoie la représentation ISO WKT, de sorte que la sortie imprimée correspond à ce qui a été écrit dans le fichier.

La symétrie est le point : les colonnes d’attributs se comportent de la même manière, qu’une géométrie soit incluse ou non, de sorte que vous pouvez activer ou désactiver la colonne WKT sans toucher au reste de votre pipeline.

Reprojeter lors de la conversion

Si le système consommateur attend un système de coordonnées spécifique, demandez‑le dans le cadre de la conversion plutôt que de post‑traiter le CSV. ConversionOptions porte une référence spatiale ainsi que les options du pilote :

var conversionOptions = new ConversionOptions
{
    DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" },
    DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84
};

VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv, conversionOptions);

Tous les pilotes de destination ne prennent pas en charge tous les systèmes de référence spatiale. Appelez Drivers.Csv.SupportsSpatialReferenceSystem(...) d’abord si le système cible est configurable à l’exécution, puis revenez à un objet d’options null lorsqu’il n’est pas pris en charge.

Conversion par lots d’un dossier de fichiers TopoJSON

L’API est identique pour un fichier et pour mille. La seule règle à retenir lors de la parallélisation est que chaque travailleur a besoin de ses propres objets de couche et d’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}");
        }
    });
}

Capturer GisException par fichier plutôt qu’autour de toute la boucle signifie qu’un fichier TopoJSON malformé enregistre un avertissement au lieu d’interrompre le lot.

Obtenez une licence gratuite

Aspose.GIS fonctionne en mode d’évaluation jusqu’à ce qu’une licence soit appliquée. Demandez une licence temporaire gratuite depuis la page de licence temporaire Aspose et appliquez‑la une fois au démarrage de l’application, avant tout autre appel Aspose.GIS :

var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");

Ressources supplémentaires gratuites

Conclusion

La conversion de TopoJSON avec des propriétés imbriquées en CSV sous .NET repose sur un comportement utile : Aspose.GIS aplatit les objets d’attributs imbriqués en colonnes nommées telles que prop1_this pendant la lecture de la couche, de sorte que VectorLayer.Convert n’a besoin d’aucune logique personnalisée pour les conserver. Ajoutez CsvOptions.ColumnWkt lorsque le système en aval a besoin de la géométrie, ajoutez DestinationSpatialReferenceSystem lorsqu’il nécessite une projection spécifique, et répétez le même appel lorsque vous devez traiter un dossier. Le résultat est une table plate, prête pour l’analyse, produite en quelques lignes de C#, sans couche d’analyse JSON à maintenir.

FAQ

  1. Aspose.GIS peut‑il aplatir les objets JSON imbriqués lors de la conversion en CSV ? Oui. Le pilote TopoJSON expose un objet d’attribut imbriqué sous forme de colonnes séparées lorsque la couche est ouverte, en joignant les noms du parent et de l’enfant avec un soulignement, de sorte que l’aplatissement est déjà effectué avant l’exécution de la conversion.

  2. Dois-je écrire du code personnalisé pour gérer les propriétés imbriquées ? Non. VectorLayer.Convert écrit toutes les colonnes exposées par la couche source, de sorte que les propriétés imbriquées n’ont pas besoin de code d’analyse supplémentaire de votre part.

  3. Comment puis‑je inclure la géométrie dans la sortie CSV ? Créez une instance de CsvOptions, définissez sa propriété ColumnWkt sur le nom de colonne souhaité, assignez‑la à ConversionOptions.DestinationDriverOptions, puis transmettez‑la à VectorLayer.Convert.

  4. Pourquoi la géométrie est‑elle vide lorsque je relis mon CSV ? Un CSV n’a pas de colonne géométrie à moins que vous n’en demandiez une. Définissez ColumnWkt sur le CsvOptions que vous transmettez à la fois lors de l’écriture et de la lecture, sinon le pilote n’a aucune colonne à partir de laquelle construire une géométrie.

  5. Quelles exceptions dois-je gérer lors de la conversion ? Les exceptions documentées sont ArgumentNullException pour un chemin nul, ArgumentException lorsqu’un objet d’options ne correspond pas au pilote, GisException lorsqu’une fonctionnalité ne peut pas être lue depuis le fichier, et IOException pour les échecs d’E/S sous-jacents.

  6. Puis-je convertir un lot de fichiers TopoJSON en une seule fois ? Oui. Parcourez la liste des fichiers et appelez VectorLayer.Convert pour chaque fichier. Si vous parallélisez la boucle, donnez à chaque travailleur sa propre instance de VectorLayer et des options plutôt que de partager une seule instance entre les threads.

  7. La conversion modifie-t-elle le système de coordonnées ? Pas par défaut. Pour reprojeter pendant la conversion, définissez ConversionOptions.DestinationSpatialReferenceSystem sur le système cible avant d’appeler Convert.

En savoir plus