diff -r f0202c3daa7a Lib/json/encoder.py --- a/Lib/json/encoder.py Fri Aug 23 03:22:15 2013 -0500 +++ b/Lib/json/encoder.py Fri Aug 23 14:55:28 2013 +0400 @@ -322,6 +322,30 @@ if markers is not None: del markers[markerid] + def _encode_dict_key(key, recursed=False): + if isinstance(key, str): + pass + # JavaScript is weakly typed for these, so it makes sense to + # also allow them. Many encoders seem to do something like this. + elif isinstance(key, float): + # see comment for int/float in _make_iterencode + key = _floatstr(float(key)) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, int): + # see comment for int/float in _make_iterencode + key = str(int(key)) + elif not recursed: + key = _default(key) + key = _encode_dict_key(key, recursed=True) + else: + raise TypeError("key " + repr(key) + " is not a string") + return key + def _iterencode_dict(dct, _current_indent_level): if not dct: yield '{}' @@ -346,26 +370,13 @@ else: items = dct.items() for key, value in items: - if isinstance(key, str): - pass - # JavaScript is weakly typed for these, so it makes sense to - # also allow them. Many encoders seem to do something like this. - elif isinstance(key, float): - # see comment for int/float in _make_iterencode - key = _floatstr(float(key)) - elif key is True: - key = 'true' - elif key is False: - key = 'false' - elif key is None: - key = 'null' - elif isinstance(key, int): - # see comment for int/float in _make_iterencode - key = str(int(key)) - elif _skipkeys: - continue - else: - raise TypeError("key " + repr(key) + " is not a string") + try: + key = _encode_dict_key(key) + except TypeError: + if _skipkeys: + continue + else: + raise if first: first = False else: