Permalink
Browse files

Add support for converting geojson to csv. Closes #183.

  • Loading branch information...
1 parent 3810579 commit c13ea6ed2aee0a3f53f3b297ee7c4e8fc2a8a19d @onyxfish onyxfish committed Aug 23, 2012
@@ -1,13 +1,14 @@
#!/usr/bin/env python
from csvitself import csv2csv
+from dbase import dbf2csv
from fixed import fixed2csv
+from geojs import geojson2csv
from js import json2csv
from xls import xls2csv
from xlsx import xlsx2csv
-from dbase import dbf2csv
-SUPPORTED_FORMATS = ['fixed', 'xls', 'xlsx', 'csv', 'json', 'dbf']
+SUPPORTED_FORMATS = ['fixed', 'xls', 'xlsx', 'csv', 'json', 'geojson', 'dbf']
def convert(f, format, schema=None, key=None, **kwargs):
"""
@@ -30,6 +31,8 @@ def convert(f, format, schema=None, key=None, **kwargs):
return xlsx2csv(f, **kwargs)
elif format == 'json':
return json2csv(f, key, **kwargs)
+ elif format == 'geojson':
+ return geojson2csv(f, **kwargs)
elif format == 'csv':
return csv2csv(f, **kwargs)
elif format == 'dbf':
View
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+from cStringIO import StringIO
+import json
+
+from csvkit import CSVKitWriter
+
+def geojson2csv(f, key=None, **kwargs):
+ """
+ Convert a GeoJSON document into CSV format.
+ """
+ document = f.read()
+ js = json.loads(document)
+
+ if not isinstance(js, dict):
+ raise TypeError('JSON document is not valid GeoJSON: Root element is not an object.')
+
+ if 'type' not in js:
+ raise TypeError('JSON document is not valid GeoJSON: No top-level "type" key.')
+
+ if js['type'] != 'FeatureCollection':
+ raise TypeError('Only GeoJSON with root FeatureCollection type is supported. Not %s' % js['type'])
+
+ if 'features' not in js:
+ raise TypeError('JSON document is not a valid FeatureCollection: No top-level "features" key.')
+
+ features = js['features']
+
+ features_parsed = [] # tuples in the format (id, properties, geometry)
+ property_set = set()
+
+ for feature in features:
+ geoid = feature.get('id', None)
+
+ properties = feature.get('properties') or {}
+ property_set.update(properties.keys())
+
+ geometry = json.dumps(feature['geometry'])
+
+ features_parsed.append((geoid, properties, geometry))
+
+ header = ['id']
+ fields = sorted(list(property_set))
+ header.extend(fields)
+ header.append('geojson')
+
+ o = StringIO()
+ writer = CSVKitWriter(o)
+
+ writer.writerow(header)
+
+ for geoid, properties, geometry in features_parsed:
+ row = [geoid]
+
+ for field in fields:
+ row.append(properties.get(field, None))
+
+ row.append(geometry)
+
+ writer.writerow(row)
+
+ output = o.getvalue()
+ o.close()
+
+ return output
+
@@ -0,0 +1,4 @@
+id,prop0,prop1,geojson
+,value0,,"{""type"": ""Point"", ""coordinates"": [102.0, 0.5]}"
+,value0,0.0,"{""type"": ""LineString"", ""coordinates"": [[102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]]}"
+,value0,{u'this': u'that'},"{""type"": ""Polygon"", ""coordinates"": [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]]}"
View
@@ -0,0 +1,49 @@
+{
+ "type": "FeatureCollection",
+ "features": [{
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [102.0, 0.5]
+ },
+ "properties": {
+ "prop0": "value0"
+ }
+ }, {
+ "type": "Feature",
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [102.0, 0.0],
+ [103.0, 1.0],
+ [104.0, 0.0],
+ [105.0, 1.0]
+ ]
+ },
+ "properties": {
+ "prop0": "value0",
+ "prop1": 0.0
+ }
+ }, {
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [
+ [
+ [100.0, 0.0],
+ [101.0, 0.0],
+ [101.0, 1.0],
+ [100.0, 1.0],
+ [100.0, 0.0]
+ ]
+ ]
+ },
+ "properties": {
+ "prop0": "value0",
+ "prop1": {
+ "this": "that"
+ }
+ }
+ }]
+}
+
@@ -26,6 +26,16 @@ def test_guess_fixed(self):
def test_guess_xls(self):
self.assertEqual('xls', convert.guess_format('testdata.xls'))
+
+ def test_guess_xlsx(self):
+ self.assertEqual('xlsx', convert.guess_format('testdata.xlsx'))
def test_guess_csv(self):
self.assertEqual('csv', convert.guess_format('testdata.csv'))
+
+ def test_guess_dbf(self):
+ self.assertEqual('dbf', convert.guess_format('testdata.dbf'))
+
+ def test_guess_json(self):
+ self.assertEqual('json', convert.guess_format('testdata.json'))
+

1 comment on commit c13ea6e

Nice work!

Please sign in to comment.