jazzband / geojson

Python bindings and utilities for GeoJSON
https://pypi.python.org/pypi/geojson/
BSD 3-Clause "New" or "Revised" License
898 stars 120 forks source link

Using the FeatureCollection class in a dataclass then trying to use asdict fails #153

Open sbland opened 3 years ago

sbland commented 3 years ago

I'm trying to store an instance of a feature collection inside a dataclass but when using the asdict function to parse the dataclass it fails with TypeError: Object of type generator is not JSON serializable

Python Version 3.8.6

Test case:

# %%

from dataclasses import dataclass, field, asdict
from geojson import FeatureCollection

# %%
@dataclass
class Temp:
    geoData: FeatureCollection = field(default_factory=lambda: FeatureCollection([]))

t = Temp()
t.features = []
asdict(t)

Stack trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\venv\lib\site-packages\geojson\base.py", line 27, in __repr__
    return geojson.dumps(self, sort_keys=True)
  File "...\venv\lib\site-packages\geojson\codec.py", line 31, in dumps
    return json.dumps(to_mapping(obj),
  File "..\Python38\lib\json\__init__.py", line 234, in dumps
    return cls(
  File "..\Python38\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "..\Python38\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "...\venv\lib\site-packages\geojson\codec.py", line 14, in default
    return geojson.factory.GeoJSON.to_instance(obj) # NOQA
  File "...\venv\lib\site-packages\geojson\base.py", line 101, in to_instance
    mapping = to_mapping(ob)
  File "...\venv\lib\site-packages\geojson\mapping.py", line 42, in to_mapping
    return json.loads(json.dumps(obj))
  File "..\Python38\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "..\Python38\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "..\Python38\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "..\Python38\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type generator is not JSON serializable
NoharaMasato commented 1 year ago

I also encountered this error. FeatureCollection class inherits dict class and asdict method tries to deep-copy the FeatureCollection object to another FeatureCollection object (here). But, constructor of FeatureCollection class takes features as a first argument. You can see the same error when running the following code.

from geojson import FeatureCollection
print(FeatureCollection((k, v) for k, v in FeatureCollection(features=[]).items()))

Dict class works for almost same code.

print(dict((k, v) for k, v in dict(features=[]).items()))

I think FeatureCollection class should behave in the same way as dict in order to be used as a attribute of dataclass.