Convert python decimal to string in deeply nested and unpredictable list

后端 未结 2 522
悲&欢浪女
悲&欢浪女 2020-12-06 22:52

I am trying to loop through every value in a deeply nested/mixed list and convert any Decimal instances to string so that I can store them in mongo.

My attempt at re

相关标签:
2条回答
  • 2020-12-06 23:24

    To convert Decimal during json.dump() using default parameter:

    import json
    import sys
    from decimal import Decimal
    
    def default(obj):
        if isinstance(obj, Decimal):
            return str(obj)
        else:
            raise TypeError(obj)
    
    # convert during dump
    json.dump(data, sys.stdout, indent=2, default=default)
    

    To modify data inplace:

    import json
    import sys
    from collections import MutableMapping, MutableSequence
    from decimal import Decimal
    
    def convert_decimal(json_data):
        stack = [json_data]
        while stack:
            json_data = stack.pop()
            if isinstance(json_data, MutableMapping): # json object
                it = json_data.items()
            elif isinstance(json_data, MutableSequence): # json array
                it = enumerate(json_data)
            else: # scalar data
                continue
    
            for k, v in it:
                if isinstance(v, Decimal):
                    json_data[k] = str(v)
                else:
                    stack.append(v)
    
    
    # convert inplace
    convert_decimal(data)
    json.dump(data, sys.stdout, indent=2)
    

    Both scripts produce the same output:

    [
      {
        "Payments": {
          "OtherFees": "0", 
          "APR": "2.54", 
          "Rate": "0.0254", 
          "IsCapped": true, 
          "Name": "TestData", 
          "Program": {
            "Description": null, 
            "ProgramName": "AST"
          }, 
          "AppliedIds": [], 
          "CapCostTotal": "27900", 
          "Tax": "0", 
          "Payment": "495.64"
        }
      }
    ]
    

    You could simplify convert_decimal() if you use a generic get_items() function:

    def convert_decimal(json_data):
        stack = [json_data]
        while stack:
            json_data = stack.pop()
            for k, v in get_items(json_data):
                if isinstance(v, Decimal):
                    json_data[k] = str(v)
                else:
                    stack.append(v)
    
    0 讨论(0)
  • 2020-12-06 23:25

    You want to convert decimals to strings, but recursively apply your function to the contents of lists and the values of dictionaries, otherwise return objects unchanged? Then do that:

    def strip_decimals(o):
        if type(o) == Decimal:
            return str(o)
        elif type(o) == list:
            return map(strip_decimals, o)
        elif type(o) == dict:
            return dict([(k, strip_decimals(v)) for k, v in o.iteritems()])
        else:
            return o
    

    Results in:

    [{'Payments': {'APR': '2.54',
               'AppliedIds': [],
               'CapCostTotal': '27900',
               'IsCapped': True,
               'Name': 'TestData',
               'OtherFees': '0',
               'Payment': '495.64',
               'Program': {'Description': None, 'ProgramName': u'AST'},
               'Rate': '0.0254',
               'Tax': '0'}}]
    
    0 讨论(0)
提交回复
热议问题