Search code examples
pythonjsonpickle

Jsonpickle Encoding Floats with Many Decimals as Null


I've encountered this problem a few times in my code and have been unable to reproduce it in a small case, but I'm hoping someone can point me in the right direction. It occurs when creating a save object (which basically packages up different parts of my program as a series of nested dicts, and then pickles them to write to a text file). Here is the relevant part of the code:

    so = {}
    for l in self.components.items():
        so[l[0]] = l[1].createSaveObject()
    temp = so
    print "Component SO:",temp
    print "Component Pickled:",jsonpickle.encode(temp)
    return jsonpickle.encode(temp)

So the function loops through my components, creates dictionary items for each, and then returns the pickled result. The problem is shown in the two print statements which give the following output (truncated to ignore working components that are being pickled without issue):

Component SO: {..., 'points': {201: [(43, 614.6), (268, 614.6), (268, 254.6), (43, 254.6)], 2041: [(79.5, 607.15999999999997), (304.5, 607.15999999999997), (304.5, 247.16), (79.5, 247.16)]},...}
Component Pickled: {..., "points": {"201": [{"py/tuple": [43, 614.6]}, {"py/tuple": [268, 614.6]}, {"py/tuple": [268, 254.6]}, {"py/tuple": [43, 254.6]}], "2041": [{"py/tuple": [null, null]}, {"py/tuple": [null, null]}, {"py/tuple": [null, null]}, {"py/tuple": [null, null]}]},...}

As you can see, the dictionary entry containing the high-precision numbers (and the other elements in the same section that are truncated to regular values) are encoded as null. I've failed to reproduce this from a python shell - it only occurs while the program is running. However, I am unsure how to go about finding the source, given that the only difference between the two outputs is a jsonpickle.encode call.

Thanks!


Solution

  • I had a similar issue when using the output of numpy.average. Found this code which worked in my use case:

    http://nullege.com/codes/show/src@t@i@[email protected]/472/jsonpickle.handlers.BaseHandler

    import numpy as np
    
    class NumpyFloatHandler(jsonpickle.handlers.BaseHandler):
        """
        Automatic conversion of numpy float  to python floats
        Required for jsonpickle to work correctly
        """
        def flatten(self, obj, data):
            """
            Converts and rounds a Numpy.float* to Python float
            """
            return round(obj,6)
    
    jsonpickle.handlers.registry.register(np.float, NumpyFloatHandler)
    jsonpickle.handlers.registry.register(np.float32, NumpyFloatHandler)
    jsonpickle.handlers.registry.register(np.float64, NumpyFloatHandler)