pythonjsonxmlsimplejsonpyshp

Converting/Serializing dictionaries containing a large list of value pairs into a json file in python


Currently I try to convert data from an ESRI shapefile (.shp) to a Json file using the json package.

In this process, I want to convert a dictionairy containing the coordinates of a lot of different points:

json.dumps({"Points" : coordinates}) 

The list "coordinates" looks like:

[[-2244.677490234375, -3717.6876220703125], [-2252.7623006509266, -3717.321774721159], 
..., [-2244.677490234375, -3717.6876220703125]]

and contains about several hundreds of coordinate pairs.

However, when I try to execute json.dumps, I get the following error:

[-2244.677490234375, -3717.6876220703125] is not JSON serializable

My first thought was, that it can not handle decimal/float values But if I execute the following working example containing only two of the coordinate pairs:

print(json.dumps({"Points" :  [[-2244.677490234375, -3717.6876220703125],
[-2244.677490234375, -3717.6876220703125]]}))

tt works and I do not get an error... The output in this case is:

{"Points": [[-2244.677490234375, -3717.6876220703125], [-2244.677490234375, -3717.6876220703125]]}

I don't get why it isn't working with my "coordinates"-list.


Solution

  • The error you are seeing most commonly happens with custom classes. So I believe your problem has to do with the way pyshp is supplying the coordinate values. I can't be sure without seeing your code, but looking at the pyshp source I found an _Array class that is used in a few places.

    class _Array(array.array):
      """Converts python tuples to lits of the appropritate type.
      Used to unpack different shapefile header parts."""
      def __repr__(self):
        return str(self.tolist())
    

    The __repr__ might explain why you believe you are seeing a standard list or tuple when in fact it is a custom class. I put together a python fiddle which demonstrates the exception when providing pyshp's _Array class to json.dumps().

    To fix this issue you should pass coordinates.tolist() to your dumps call.

    json.dumps({"Points" : coordinates.tolist()})