diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index 41a497c5da01603..4260e59ed1f3de3 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -256,8 +256,36 @@ def floatstr(o, allow_nan=self.allow_nan, self.skipkeys, _one_shot) return _iterencode(o, 0) +def _get_sequence_types(): + """Non-iterator sequence types that should be encoded as a json array""" + # FIXME: there are a bunch of other sequences in the Python standard library, + # such as an array.array, queue.Queue, collections.deque. + return (list, tuple, set, frozenset, bytearray) + +def _get_iterator_types(): + """Iterator types that should be encoded as a json array""" + # FIXME: Are these types defined in builtins or the standard library somewhere? + str_iterator = type(iter(str())) + list_iterator = type(iter(list())) + tuple_iterator = type(iter(tuple())) + range_iterator = type(iter(range(0))) + list_reverseiterator = type(reversed(list())) + # reverseiterator is same as + reverseiterator = type(reversed(tuple())) + dict_keyiterator = type(iter(dict().keys())) + dict_valueiterator = type(iter(dict().values())) + dict_itemiterator = type(iter(dict().items())) + return (str_iterator, list_iterator, tuple_iterator, range_iterator, + list_reverseiterator, reverseiterator, + dict_keyiterator, dict_valueiterator, dict_itemiterator) + +def _get_iterable_types(): + """Returns a tuple of all types that should be encoded as a json array""" + return _get_sequence_types() + _get_iterator_types() + def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, + iterable_types=_get_iterable_types(), ## HACK: hand-optimized bytecode; turn globals into locals ValueError=ValueError, dict=dict, @@ -316,7 +344,7 @@ def _iterencode_list(lst, _current_indent_level): yield buf + _floatstr(value) else: yield buf - if isinstance(value, (list, tuple)): + if isinstance(value, iterable_types): chunks = _iterencode_list(value, _current_indent_level) elif isinstance(value, dict): chunks = _iterencode_dict(value, _current_indent_level) @@ -395,7 +423,7 @@ def _iterencode_dict(dct, _current_indent_level): # see comment for int/float in _make_iterencode yield _floatstr(value) else: - if isinstance(value, (list, tuple)): + if isinstance(value, iterable_types): chunks = _iterencode_list(value, _current_indent_level) elif isinstance(value, dict): chunks = _iterencode_dict(value, _current_indent_level) @@ -424,7 +452,7 @@ def _iterencode(o, _current_indent_level): elif isinstance(o, float): # see comment for int/float in _make_iterencode yield _floatstr(o) - elif isinstance(o, (list, tuple)): + elif isinstance(o, iterable_types): yield from _iterencode_list(o, _current_indent_level) elif isinstance(o, dict): yield from _iterencode_dict(o, _current_indent_level)