TopoJSON é uma codificação compacta de dados geográficos, e é comum que cada recurso em um arquivo TopoJSON carregue um objeto de atributos em vez de um conjunto plano de pares chave‑valor. Exportar essa estrutura para CSV é onde as coisas geralmente dão errado: a maioria das ferramentas ou descarta o objeto aninhado ou o despeja de volta como uma string JSON inserida em uma única célula. Este guia mostra como converter TopoJSON para CSV em C# usando Aspose.GIS, mantendo cada atributo endereçável como sua própria coluna e, opcionalmente, gravando a geometria ao lado como Well‑Known Text.
A vantagem é que um conjunto de dados GIS hierárquico se torna uma tabela plana que o SQL Server, o Power BI, o pandas ou uma planilha simples podem consumir diretamente, sem uma camada personalizada de análise JSON em sua aplicação.
Por que converter TopoJSON para CSV usando Aspose.GIS
Considere um recurso TopoJSON cujas propriedades se parecem com isto:
{
"name": "North District",
"prop1": { "this": "that" }
}
Um escritor CSV ingênuo tem três opções ruins: descartar prop1, serializá‑lo como {"this":"that"} em uma única célula ou falhar. Todas as três empurram o problema para baixo, onde alguém precisa reanalisar o JSON de uma coluna de texto antes de poder filtrar ou fazer join nele.
Aspose.GIS adota uma abordagem diferente. Quando o driver TopoJSON lê o arquivo, ele projeta o objeto aninhado no esquema da camada como um atributo plano nomeado de acordo com seu caminho, unindo pai e filho com um sublinhado. O recurso acima é exposto como duas colunas comuns:
| Coluna | Valor |
|---|---|
name | Distrito Norte |
prop1_this | isso |
Como o achatamento ocorre no momento da leitura, a etapa de conversão não precisa de nenhum tratamento especial. O que quer que a camada exponha é o que é gravado, então prop1_this aparece no CSV como uma coluna de primeira classe que você pode ordenar, filtrar e fazer junções.
Pré-requisitos da Conversão de TopoJSON para CSV
- .NET 6.0 ou posterior, ou .NET Framework 4.6.2 ou posterior
- Aspose.GIS for .NET, instalado a partir do NuGet
- Um arquivo TopoJSON contendo pelo menos um objeto de atributo aninhado
Instale o pacote com o .NET CLI:
dotnet add package Aspose.GIS
Ou pelo Console do Gerenciador de Pacotes:
Install-Package Aspose.GIS
Um detalhe de nomenclatura pega as pessoas desprevenidas: o pacote NuGet e o assembly são chamados Aspose.GIS, mas o namespace raiz é Aspose.Gis com um is minúsculo. As opções do driver CSV estão em Aspose.Gis.Formats.Csv.
using Aspose.Gis;
using Aspose.Gis.Formats.Csv;
Os detalhes do produto estão na página do produto Aspose.GIS for .NET, com a lista completa de tipos na referência da API.
Inspecione o Esquema Achatado Antes de Converter
O que você vai realizar: Abra a camada TopoJSON e imprima os nomes dos atributos para saber exatamente quais colunas o CSV conterá.
Esta etapa vale a pena ser feita uma vez em um arquivo representativo. Ela informa os nomes reais das colunas gerados pelo achatamento, o que é muito mais confiável do que adivinhá‑los a partir do JSON bruto.
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})");
}
}
Para o recurso de exemplo mostrado anteriormente, isso imprime name (String) e prop1_this (String). O objeto aninhado nunca aparece como um atributo por si só, o que é exatamente o que você deseja.
Converter TopoJSON para CSV preservando atributos aninhados
O que você vai realizar: Carregue um arquivo TopoJSON, escreva cada atributo achatado em um arquivo CSV e leia o resultado de volta para confirmar que a coluna foi preservada.
Processo passo a passo
- Defina o caminho de origem do TopoJSON e o caminho de destino do CSV.
- Abra a origem com
VectorLayer.Opene confirme que o atributo achatado existe. - Chame a sobrecarga estática
VectorLayer.Convertcom os drivers de origem e destino. - Reabra o CSV com
Drivers.Csve verifique a contagem de colunas e os valores.
O exemplo a seguir converte um arquivo TopoJSON para CSV, achatando propriedades aninhadas ao longo do caminho.
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}");
}
}
}
Explicação
VectorLayer.Open(string, FileDriver)abre o arquivo somente leitura.Drivers.TopoJsondevolve o driver para o formato TopoJSON.FeatureAttributeCollection.Contains(string)é a maneira mais econômica de testar a existência de uma coluna por nome.IndexOffornece sua posição caso você precise.VectorLayer.Convert(string, FileDriver, string, FileDriver)é um helper estático que transmite a origem para o formato de destino em uma única chamada. Também há uma sobrecarga que aceitaConversionOptions, usada na seção seguinte.Feature.GetValue<T>(string)lê um valor de atributo tipado. UseGetValueOrDefault<T>(string)quando uma coluna pode estar ausente ou nula, já queGetValue<T>assume que o valor está presente.- A verificação final é a que surpreende as pessoas. Um arquivo CSV não possui coluna de geometria a menos que você crie uma, portanto cada feature retorna com geometria vazia. Esse é o comportamento padrão, não uma falha de conversão, e a seção seguinte corrige isso.
Envolver ambas as camadas em blocos using é importante aqui: VectorLayer implementa IDisposable e o arquivo de destino não tem garantia de ser descarregado e fechado até que seja descartado.
Incluir Geometria como WKT Usando CsvOptions
O que você realizará: Produza um CSV que contenha tanto os atributos achatados e uma coluna contendo a geometria de cada recurso como Well-Known Text.
Processo passo a passo
- Crie uma instância de
CsvOptionse definaColumnWktpara o nome da coluna escolhido. - Atribua‑a a
ConversionOptions.DestinationDriverOptions. - Chame a sobrecarga
VectorLayer.Convertque aceita opções de conversão. - Reabra o CSV com o mesmo
CsvOptionspara que o driver saiba qual coluna analisar como geometria.
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}");
}
}
}
}
Explicação
CsvOptions.ColumnWktnomeia a coluna que contém a geometria de cada recurso em forma WKT. O padrão énull, e deixá‑la nula ou vazia é exatamente o motivo pelo qual o exemplo anterior não produziu geometria.ConversionOptions.DestinationDriverOptionsé tipado comoDriverOptions, a classe base para o objeto de configurações de cada driver. Passar umCsvOptionsonde o driver de destino éDrivers.Csvé o que faz a configuração ter efeito; passar opções do tipo errado para um driver gera umaArgumentException.- A mesma instância de
CsvOptionsé reutilizada no lado de leitura. Sem ela, o driver CSV não tem razão para tratarGeometryWktcomo algo diferente de outra coluna de string. IGeometry.AsText()retorna a representação ISO WKT, portanto a saída impressa corresponde ao que foi escrito no arquivo.
A simetria é o ponto: as colunas de atributos se comportam de forma idêntica, independentemente de a geometria estar incluída ou não, de modo que você pode ativar e desativar a coluna WKT sem tocar no restante do seu pipeline.
Reprojetar durante a conversão
Se o sistema consumidor espera um sistema de coordenadas específico, solicite‑o como parte da conversão em vez de pós‑processar o CSV. ConversionOptions carrega uma referência espacial juntamente com as opções do driver:
var conversionOptions = new ConversionOptions
{
DestinationDriverOptions = new CsvOptions { ColumnWkt = "GeometryWkt" },
DestinationSpatialReferenceSystem = SpatialReferenceSystem.Wgs84
};
VectorLayer.Convert(sourcePath, Drivers.TopoJson, destinationPath, Drivers.Csv, conversionOptions);
Nem todo driver de destino suporta todos os sistemas de referência espacial. Chame Drivers.Csv.SupportsSpatialReferenceSystem(...) primeiro se o sistema de destino for configurável em tempo de execução e recorra a um objeto de opções nulo quando não for suportado.
Conversão em lote de uma pasta de arquivos TopoJSON
A API é idêntica para um arquivo e para mil. A única regra que vale a pena lembrar ao paralelizar é que cada worker precisa de seus próprios objetos de camada e de opções.
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}");
}
});
}
Capturar GisException por arquivo em vez de ao redor de todo o loop significa que um arquivo TopoJSON malformado registra um aviso em vez de abortar o lote.
Obtenha uma Licença Gratuita
O Aspose.GIS funciona em modo de avaliação até que uma licença seja aplicada. Solicite uma licença temporária gratuita na página de licença temporária da Aspose e aplique‑a uma vez na inicialização da aplicação, antes de qualquer outra chamada ao Aspose.GIS:
var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");
Recursos Adicionais Gratuitos
Conclusão
Converter TopoJSON com propriedades aninhadas para CSV em .NET se resume a um comportamento útil: Aspose.GIS achata objetos de atributos aninhados em colunas nomeadas como prop1_this enquanto a camada está sendo lida, portanto VectorLayer.Convert não precisa de lógica personalizada para preservá‑los. Adicione CsvOptions.ColumnWkt quando o sistema downstream precisar de geometria, adicione DestinationSpatialReferenceSystem quando precisar de uma projeção específica e repita a mesma chamada quando precisar processar uma pasta. O resultado é uma tabela plana, pronta para análise, produzida por algumas linhas de C#, sem a necessidade de manter uma camada de análise JSON própria.
FAQs
O Aspose.GIS pode achatar objetos JSON aninhados ao converter para CSV? Sim. O driver TopoJSON expõe um objeto de atributo aninhado como colunas separadas quando a camada é aberta, unindo os nomes do pai e do filho com um sublinhado, de modo que o achatamento já é realizado antes da execução da conversão.
Preciso escrever código personalizado para lidar com propriedades aninhadas? Não.
VectorLayer.Convertgrava quaisquer colunas que a camada de origem expõe, portanto, propriedades aninhadas não precisam de código de análise extra da sua parte.Como posso incluir geometria na saída CSV? Crie uma instância de
CsvOptions, defina sua propriedadeColumnWktpara o nome da coluna que deseja, atribua‑a aConversionOptions.DestinationDriverOptionse passe isso paraVectorLayer.Convert.Por que a geometria está vazia quando leio meu CSV de volta? Um CSV não tem coluna de geometria a menos que você solicite uma. Defina
ColumnWktnasCsvOptionsque você passa tanto ao gravar quanto ao ler, caso contrário o driver não tem coluna da qual construir uma geometria.Quais exceções devo tratar durante a conversão? As documentadas são
ArgumentNullExceptionpara um caminho nulo,ArgumentExceptionquando um objeto de opções não corresponde ao driver,GisExceptionquando um recurso não pode ser lido do arquivo eIOExceptionpara falhas subjacentes de E/S.Posso converter um lote de arquivos TopoJSON de uma vez? Sim. Percorra a lista de arquivos e chame
VectorLayer.Convertpara cada arquivo. Se você paralelizar o loop, dê a cada trabalhador sua própria instância deVectorLayere de opções, em vez de compartilhar uma entre as threads.A conversão altera o sistema de coordenadas? Não por padrão. Para reprojetar durante a conversão, defina
ConversionOptions.DestinationSpatialReferenceSystempara o sistema de destino antes de chamarConvert.
