Neste artigo eu explico como converter um arquivo no formato JSON para shapefile usando a biblioteca Gdal em C#. Segue um exemplo de arquivo JSON (você também pode baixar o arquivo completo):
{ "features": [{ "geometry": { "coordinates": [-37.2726631195437, -9.91254751352393], "type": "Point" }, "properties": { "identifier": "12", "serial_number": "29213220", "name": "POINT-10", "length": 3.0 }, "type": "Feature" }, { "geometry": { "coordinates": [-37.2726722686872, -9.91252509027536], "type": "Point" }, "properties": { "identifier": "11", "serial_number": "29213220", "name": "POINT-10", "length": 4.0, }, "type": "Feature" } }
Vamos para o passo a passo:
Primeiramente, importamos o Gdal para o projeto: no Visual Studio, clique com o botão direito no projeto, vá em "Manage NuGet packages", digite "Gdal" no campo de busca, selecione o Gdal (1.11.1 é a última versão disponível até o momento em que este artigo foi escrito) e instale. Selecione e instale também o Gdal.Native (sem ele o projeto compila mas não executa corretamente). A classe "GdalConfiguration.cs" será criada automaticamente. Ela será usada antes de iniciar o método para conversão.
Para zipar os arquivos gerados do shapefile, será necessária também a biblioteca "DotNetZip". Adicione-a também pelo "Manage NuGet packages". Caso não queira essa funcionalidade, não é necessário instalar.
Para importá-lo em sua classe use:
using OSGeo.OGR; using OSGeo.OSR;
Antes de usar as classes do Gdal, precisamos configurá-lo. Para isso, basta chamar os métodos ConfigureGdal e ConfigureOgr da classe GdalConfiguration.cs. Você pode chamá-los, por exemplo, no construtor de sua classe.
public GdalUtilities() {
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
}
Código para abrir o arquivo JSON com o Gdal e pegar sua camada:
Driver jsonFileDriver = Ogr.GetDriverByName("GeoJSON"); DataSource jsonFile = Ogr.Open(jsonFilePath, 0); if(jsonFile == null) { return false; } Layer jsonLayer = jsonFile.GetLayerByIndex(0);
Código para criar o arquivo shapefile com o Gdal. Caso o arquivo já exista ele será removido.
string filesPathName = shapeFilePath.Substring(0, shapeFilePath.Length - 4); removeShapeFileIfExists(filesPathName); Driver esriShapeFileDriver = Ogr.GetDriverByName("ESRI Shapefile"); DataSource shapeFile = esriShapeFileDriver.CreateDataSource(shapeFilePath, new string[] { }); Layer shplayer = shapeFile.CreateLayer(jsonLayer.GetName(), jsonLayer.GetSpatialRef(), jsonLayer.GetGeomType(), new string[] { });
Código para criar copiar as propriedades e valores de cada elemento do arquivo JSON para o novo shapefile criado:
// create fields (properties) in new layer Feature jsonFeature = jsonLayer.GetNextFeature(); for(int i = 0; i < jsonFeature.GetFieldCount(); i++) { FieldDefn fieldDefn = new FieldDefn(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldDefnRef(i).GetFieldType()); shplayer.CreateField(fieldDefn, 1); } while(jsonFeature != null) { Geometry geometry = jsonFeature.GetGeometryRef(); Feature shpFeature = createGeometryFromGeometry(geometry, shplayer, jsonLayer.GetSpatialRef()); // copy values for each field for(int i = 0; i < jsonFeature.GetFieldCount(); i++) { if(FieldType.OFTInteger == jsonFeature.GetFieldDefnRef(i).GetFieldType()) { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsInteger(i)); } else if(FieldType.OFTReal == jsonFeature.GetFieldDefnRef(i).GetFieldType()) { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsDouble(i)); } else { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsString(i)); } } shplayer.SetFeature(shpFeature); jsonFeature = jsonLayer.GetNextFeature(); }
Código para fechar o shapefile criado e setado e zipar todos arquivos gerados.
shapeFile.Dispose(); // if you want to generate zip of generated files string zipName = filesPathName + ".zip"; CompressToZipFile(new List<string>() { shapeFilePath, filesPathName + ".dbf", filesPathName + ".prj", filesPathName + ".shx" }, zipName);
new GdalUtilities().convertJsonToShapeFile(@"C:\development\example-data.json", @"C:\development\shapefile-out.shp");
using OSGeo.OGR; using OSGeo.OSR; using System.Collections.Generic; using Ionic.Zip; using System.IO; namespace Adadev.GdalModule { public class GdalUtilities { public GdalUtilities() { GdalConfiguration.ConfigureGdal(); GdalConfiguration.ConfigureOgr(); } public bool convertJsonToShapeFile(string jsonFilePath, string shapeFilePath) { Driver jsonFileDriver = Ogr.GetDriverByName("GeoJSON"); DataSource jsonFile = Ogr.Open(jsonFilePath, 0); if(jsonFile == null) { return false; } string filesPathName = shapeFilePath.Substring(0, shapeFilePath.Length - 4); removeShapeFileIfExists(filesPathName); Layer jsonLayer = jsonFile.GetLayerByIndex(0); Driver esriShapeFileDriver = Ogr.GetDriverByName("ESRI Shapefile"); DataSource shapeFile = Ogr.Open(shapeFilePath, 0); shapeFile = esriShapeFileDriver.CreateDataSource(shapeFilePath, new string[] { }); Layer shplayer = shapeFile.CreateLayer(jsonLayer.GetName(), jsonLayer.GetSpatialRef(), jsonLayer.GetGeomType(), new string[] { }); // create fields (properties) in new layer Feature jsonFeature = jsonLayer.GetNextFeature(); for(int i = 0; i < jsonFeature.GetFieldCount(); i++) { FieldDefn fieldDefn = new FieldDefn(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldDefnRef(i).GetFieldType()); shplayer.CreateField(fieldDefn, 1); } while(jsonFeature != null) { Geometry geometry = jsonFeature.GetGeometryRef(); Feature shpFeature = createGeometryFromGeometry(geometry, shplayer, jsonLayer.GetSpatialRef()); // copy values for each field for(int i = 0; i < jsonFeature.GetFieldCount(); i++) { if(FieldType.OFTInteger == jsonFeature.GetFieldDefnRef(i).GetFieldType()) { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsInteger(i)); } else if(FieldType.OFTReal == jsonFeature.GetFieldDefnRef(i).GetFieldType()) { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsDouble(i)); } else { shpFeature.SetField(getValidFieldName(jsonFeature.GetFieldDefnRef(i)), jsonFeature.GetFieldAsString(i)); } } shplayer.SetFeature(shpFeature); jsonFeature = jsonLayer.GetNextFeature(); } shapeFile.Dispose(); // if you want to generate zip of generated files string zipName = filesPathName + ".zip"; CompressToZipFile(new List<string>() { shapeFilePath, filesPathName + ".dbf", filesPathName + ".prj", filesPathName + ".shx" }, zipName); return true; } private void removeShapeFileIfExists(string filesPathName) { removeFileIfExists(filesPathName + ".shp"); removeFileIfExists(filesPathName + ".shx"); removeFileIfExists(filesPathName + ".prj"); removeFileIfExists(filesPathName + ".zip"); } public static bool removeFileIfExists(string filePath) { if(File.Exists(filePath)) { File.Delete(filePath); return true; } return false; } // the field names in shapefile have limit of 10 characteres private string getValidFieldName(FieldDefn fieldDefn) { string fieldName = fieldDefn.GetName(); return fieldName.Length > 10 ? fieldName.Substring(0, 10) : fieldName; } private Feature createGeometryFromGeometry(Geometry geometry, Layer layer, SpatialReference reference) { Feature feature = new Feature(layer.GetLayerDefn()); string wktgeometry = ""; geometry.ExportToWkt(out wktgeometry); Geometry newGeometry = Geometry.CreateFromWkt(wktgeometry); newGeometry.AssignSpatialReference(reference); feature.SetGeometry(newGeometry); layer.CreateFeature(feature); return feature; } public static void CompressToZipFile(List<string> files, string zipPath) { using(ZipFile zip = new ZipFile()) { foreach(string file in files) { zip.AddFile(file, ""); } zip.Save(zipPath); } } } }
Você pode baixar o código completo e arquivos de exemplo no nosso repositório no Github.
Ler e Escrever Imagens com o Gdal em C#
Algoritmo Balanço de Branco com Gdal em C#