Python JSON serialize a Decimal object

后端 未结 17 1173
星月不相逢
星月不相逢 2020-11-22 08:27

I have a Decimal(\'3.9\') as part of an object, and wish to encode this to a JSON string which should look like {\'x\': 3.9}. I don\'t care about p

相关标签:
17条回答
  • 2020-11-22 09:27

    How about subclassing json.JSONEncoder?

    class DecimalEncoder(json.JSONEncoder):
        def default(self, o):
            if isinstance(o, decimal.Decimal):
                # wanted a simple yield str(o) in the next line,
                # but that would mean a yield on the line with super(...),
                # which wouldn't work (see my comment below), so...
                return (str(o) for o in [o])
            return super(DecimalEncoder, self).default(o)
    

    Then use it like so:

    json.dumps({'x': decimal.Decimal('5.5')}, cls=DecimalEncoder)
    
    0 讨论(0)
  • 2020-11-22 09:27

    I would like to let everyone know that I tried Michał Marczyk's answer on my web server that was running Python 2.6.5 and it worked fine. However, I upgraded to Python 2.7 and it stopped working. I tried to think of some sort of way to encode Decimal objects and this is what I came up with:

    import decimal
    
    class DecimalEncoder(json.JSONEncoder):
        def default(self, o):
            if isinstance(o, decimal.Decimal):
                return float(o)
            return super(DecimalEncoder, self).default(o)
    

    This should hopefully help anyone who is having problems with Python 2.7. I tested it and it seems to work fine. If anyone notices any bugs in my solution or comes up with a better way, please let me know.

    0 讨论(0)
  • 2020-11-22 09:27

    My $.02!

    I extend a bunch of the JSON encoder since I am serializing tons of data for my web server. Here's some nice code. Note that it's easily extendable to pretty much any data format you feel like and will reproduce 3.9 as "thing": 3.9

    JSONEncoder_olddefault = json.JSONEncoder.default
    def JSONEncoder_newdefault(self, o):
        if isinstance(o, UUID): return str(o)
        if isinstance(o, datetime): return str(o)
        if isinstance(o, time.struct_time): return datetime.fromtimestamp(time.mktime(o))
        if isinstance(o, decimal.Decimal): return str(o)
        return JSONEncoder_olddefault(self, o)
    json.JSONEncoder.default = JSONEncoder_newdefault
    

    Makes my life so much easier...

    0 讨论(0)
  • 2020-11-22 09:27

    this can be done by adding

        elif isinstance(o, decimal.Decimal):
            yield str(o)
    

    in \Lib\json\encoder.py:JSONEncoder._iterencode, but I was hoping for a better solution

    0 讨论(0)
  • 2020-11-22 09:28

    The native option is missing so I'll add it for the next guy/gall that looks for it.

    Starting on Django 1.7.x there is a built-in DjangoJSONEncoder that you can get it from django.core.serializers.json.

    import json
    from django.core.serializers.json import DjangoJSONEncoder
    from django.forms.models import model_to_dict
    
    model_instance = YourModel.object.first()
    model_dict = model_to_dict(model_instance)
    
    json.dumps(model_dict, cls=DjangoJSONEncoder)
    

    Presto!

    0 讨论(0)
提交回复
热议问题