使用 'json.loads()' 对格式化为字符串的整数进行类型转换

Typecast an integer formatted as a string with 'json.loads()'

我有一个来自 Web 服务器的 JSON 响应,该响应将整数用引号括起来,当使用 Python 的 json 模块加载时,这有效地将它们转换为字符串。

是否有一种聪明的方法可以在 json.loads() 或之后自动转换所有整数和浮点数?

示例数据:

{
   u'qualityIndicators':{  
      u'reviewIndicator':{  
         u'activeReviewCount':u'229',
         u'activePeriodInDays':u'365',
         u'reviewsCountedSince':u'2009-02-18',
         u'reviewIndicatorPeriodSummary':{  
            u'reviewIndicatorPeriods':{  
               u'reviewIndicatorPeriod':{  
                  u'reviewIndicatorMarkSummaries':{  
                     u'reviewIndicatorMarkSummary':[  
                        {  
                           u'markDescription':u'EXCELLENT',
                           u'periodMarkCount':u'142'
                        },
                        {  
                           u'markDescription':u'GOOD',
                           u'periodMarkCount':u'17'
                        },
                        {  
                           u'markDescription':u'FAIR',
                           u'periodMarkCount':u'12'
                        },
                        {  
                           u'markDescription':u'POOR',
                           u'periodMarkCount':u'22'
                        },
                        {  
                           u'markDescription':u'VERY_POOR',
                           u'periodMarkCount':u'36'
                        }
                     ]
                  },
                  u'startDate':u'2014-03-09',
                  u'activeReviewCount':u'229',
                  u'endDate':u'2015-03-09',
                  u'periodReviewCount':u'229',
                  u'overallMark':u'3.90',
                  u'reviewIndicatorCriteria':{  
                     u'reviewIndicatorCriterion':[  
                        {  
                           u'markDescription':u'GOOD',
                           u'periodCriterionCount':u'224',
                           u'criterionDescription':u'DELIVERY',
                           u'mark':u'4.04'
                        },
                        {  
                           u'markDescription':u'GOOD',
                           u'periodCriterionCount':u'219',
                           u'criterionDescription':u'GOODS',
                           u'mark':u'4.05'
                        },
                        {  
                           u'markDescription':u'GOOD',
                           u'periodCriterionCount':u'206',
                           u'criterionDescription':u'SERVICE',
                           u'mark':u'3.59'
                        }
                     ]
                  },
                  u'overallMarkDescription':u'GOOD'
               }
            }
         },
         u'totalReviewCount':u'1911',
         u'overallMark':u'3.90',
         u'overallMarkDescription':u'GOOD'
      }
   },
   u'targetMarketISO3':u'DEU',
   u'url':u'www.zalando.de',
   u'tsId':u'X1C77CF6EE730D2E88A284D7203D1B20F',
   u'languageISO2':u'de',
   u'name':u'zalando.de'
}

一个方法是

def decode(obj):
    for k,v in obj.iteritems():
        try:
           obj[k] = int(v)
        except:
           pass 
    return obj

from json import JSONDecoder
d = JSONDecoder(object_hook=decode)
d.decode(<json_string>)
# get raw_data
import json
data = json.loads(raw_data)

def conv_num(data):
    if isinstance(data, str):
        try:
            return json.loads(data)
        except ValueError:
            return data
    elif isinstance(data, list):
        ret = []
        for v in data:
            ret.append(conv_num(v))
        return ret
    elif isinstance(data, dict):
        ret = {}
        for k, v in data.items():
            ret[k] = conv_num(v)
        return ret
    else:
        return data

data = conv_num(data)

这会将所有整数或浮点数形状的字符串转换为相应的值。

您可以通过继承 json.JSONDecoder 来实现自己的解码器:

import json


def try_casting_to(value, type_):
    try:
        value = type_(value)
    except ValueError:
        pass
    return value

def try_float(value):
    return try_casting_to(value, float)

def try_int(value):
    return try_casting_to(value, int)


class NumberDecoder(json.JSONDecoder):

    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.parse_number)

    def parse_number(self, dct):
        for key, value in dct.items():
            if isinstance(value, basestring):
                if '.' in value:
                    value = try_float(value)
                else:
                    value = try_int(value)
            dct[key] = value
        return dct


data = """
{"foo": {"baz": {"foo": {"baz": "qux", "bar": "10"}, "bar": "42.5"}}}
"""

obj = NumberDecoder().decode(data)
print obj

输出:

{u'foo': {u'baz': {u'foo': {u'bar': 10, u'baz': u'qux'}, u'bar': 42.5}}}

这只处理 values 中引号中的整数,而不处理 keys 中的整数(尽管更改很简单)。