Skip to content

fix: serialize array-valued GeoJSON properties as JSON#1348

Open
chuenchen309 wants to merge 1 commit into
wireservice:masterfrom
chuenchen309:fix/geojson-array-property-json
Open

fix: serialize array-valued GeoJSON properties as JSON#1348
chuenchen309 wants to merge 1 commit into
wireservice:masterfrom
chuenchen309:fix/geojson-array-property-json

Conversation

@chuenchen309

Copy link
Copy Markdown

The bug

in2csv --format geojson serializes an object-valued GeoJSON property as JSON, but an array-valued property is emitted as a Python repr — invalid, non-round-trippable JSON. Both container types appear side by side in the same row:

{"type":"FeatureCollection","features":[{"type":"Feature","id":1,
 "properties":{"name":"Central Park","categories":["park","landmark"],"opening_hours":{"mon":"6-1"}},
 "geometry":{"type":"Point","coordinates":[-73.965,40.782]}}]}
id,name,categories,opening_hours,...
1,Central Park,"['park', 'landmark']","{""mon"": ""6-1""}",...
  • categories (array) → ['park', 'landmark'] — Python repr, single quotes, not valid JSON
  • opening_hours (object) → {"mon": "6-1"} — JSON

Per GeoJSON (RFC 7946), a Feature's properties is a JSON object whose values may be arrays (tags, categories, times…), so array-valued properties are ordinary input.

Root cause

csvkit/convert/geojs.py:

value = properties.get(field)
if isinstance(value, OrderedDict):   # only objects get json.dumps; arrays fall through to str()/repr
    value = json.dumps(value)

That OrderedDict check was added specifically to stop emitting Python repr (CHANGELOG: "in2csv with --format geojson prints a JSON object instead of OrderedDict([(...)])"). Arrays are the other half of the same intent and were left out.

The fix

if isinstance(value, (OrderedDict, list)):
    value = json.dumps(value)

Verification

  • The repro now emits ["park", "landmark"]; the object column is unchanged.
  • Added test_geojson_array_property to tests/test_utilities/test_in2csv.py; it fails on master (the cell is the repr) and passes with the fix.
  • tests/test_convert/ + tests/test_utilities/test_in2csv.py → 68 passed. flake8 / isort clean. CHANGELOG entry added.

Not a duplicate — no open issue/PR touches geojson input conversion (the nearby closed #827 was about csvjson output, the opposite direction).


This PR was authored by an AI coding agent (Claude Code) running on this account: the AI found the bug, ran the repro, wrote the test, and wrote this description. The human account holder reviews every change and is accountable for it. The verification above is real and re-runnable from the diff. If this isn't the kind of contribution you want, say so and I'll close it.

geojson2csv only ran json.dumps on OrderedDict property values, so an
array (list) property fell through to the CSV writer's str() and was
emitted as a Python repr — e.g. ['park', 'landmark'], which is not valid
JSON and not round-trippable. An object property in the same row was
already emitted as JSON, so the two container types diverged.

This completes the intent of the existing OrderedDict json.dumps (added
per the "prints a JSON object instead of OrderedDict([(...)])" changelog
entry): dump lists as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type Error outputting to geojson with csvjson

1 participant