In this article I explain how to convert a JSON file to shapefile using Gdal library in C#. The following is an example of a valid JSON file (you can also download the complete file):
{ "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" } }
Let's go to the steps:
Firstly, we have to import Gdal to the project: in Visual Studio, right click on project, go to "Manage NuGet packages", type "Gdal" on search field, select Gdal (1.11.1 is the last version available at the time of writing) and install it. Also select and install Gdal.Native (the project compile without it but it does not execute correctly). The "GdalConfiguration.cs" class is created automatically. It is used before start the conversion method.
To zip the generated shapefile files, we need the library "DotNetZip". Install it too by "Manage NuGet packages". If you do not want to zip the files, you do not need to install it.
To import Gdal in your class, use:
using OSGeo.OGR; using OSGeo.OSR;
Before use the Gdal classes, we need to configure it. You just need to call ConfigureGdal e ConfigureOgr methods of the class GdalConfiguration.cs. You can call them, for example, in class constructor.
public GdalUtilities() {
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
}
The following is the code to open the JSON file with Gdal and get its layer:
Driver jsonFileDriver = Ogr.GetDriverByName("GeoJSON"); DataSource jsonFile = Ogr.Open(jsonFilePath, 0); if(jsonFile == null) { return false; } Layer jsonLayer = jsonFile.GetLayerByIndex(0);
The following is the code to create the shapefile with Gdal. If the file already exists, it is removed.
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[] { });
The following is the code to create and copy the properties e values of each element of JSON file to new shapefile:
// 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(); }
The following is the code to close the created shapefile and to zip all generated files:
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); } } } }
You can download the complete code and example files in our repository on Github.
Read and Write Images with Gdal in C#
White Balance Algorithm with Gdal in C#