Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
a4998a70
Kaydet (Commit)
a4998a70
authored
Agu 10, 2013
tarafından
Ethan Furman
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Close #18264: int- and float-derived enums now converted to int or float.
üst
fbcf4d78
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
178 additions
and
32 deletions
+178
-32
json.rst
Doc/library/json.rst
+20
-17
encoder.py
Lib/json/encoder.py
+19
-8
test_enum.py
Lib/test/test_json/test_enum.py
+81
-0
_json.c
Modules/_json.c
+58
-7
No files found.
Doc/library/json.rst
Dosyayı görüntüle @
a4998a70
...
...
@@ -349,23 +349,26 @@ Encoders and Decoders
.. _py-to-json-table:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
+----------------------------------------+---------------+
| Python | JSON |
+========================================+===============+
| dict | object |
+----------------------------------------+---------------+
| list, tuple | array |
+----------------------------------------+---------------+
| str | string |
+----------------------------------------+---------------+
| int, float, int- & float-derived Enums | number |
+----------------------------------------+---------------+
| True | true |
+----------------------------------------+---------------+
| False | false |
+----------------------------------------+---------------+
| None | null |
+----------------------------------------+---------------+
.. versionchanged:: 3.4
Added support for int- and float-derived Enum classes.
To extend this to recognize other objects, subclass and implement a
:meth:`default` method with another method that returns a serializable object
...
...
Lib/json/encoder.py
Dosyayı görüntüle @
a4998a70
...
...
@@ -175,6 +175,7 @@ class JSONEncoder(object):
def
encode
(
self
,
o
):
"""Return a JSON string representation of a Python data structure.
>>> from json.encoder import JSONEncoder
>>> JSONEncoder().encode({"foo": ["bar", "baz"]})
'{"foo": ["bar", "baz"]}'
...
...
@@ -298,9 +299,13 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
elif
value
is
False
:
yield
buf
+
'false'
elif
isinstance
(
value
,
int
):
yield
buf
+
str
(
value
)
# Subclasses of int/float may override __str__, but we still
# want to encode them as integers/floats in JSON. One example
# within the standard library is IntEnum.
yield
buf
+
str
(
int
(
value
))
elif
isinstance
(
value
,
float
):
yield
buf
+
_floatstr
(
value
)
# see comment above for int
yield
buf
+
_floatstr
(
float
(
value
))
else
:
yield
buf
if
isinstance
(
value
,
(
list
,
tuple
)):
...
...
@@ -346,7 +351,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
# 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
):
key
=
_floatstr
(
key
)
# see comment for int/float in _make_iterencode
key
=
_floatstr
(
float
(
key
))
elif
key
is
True
:
key
=
'true'
elif
key
is
False
:
...
...
@@ -354,7 +360,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
elif
key
is
None
:
key
=
'null'
elif
isinstance
(
key
,
int
):
key
=
str
(
key
)
# see comment for int/float in _make_iterencode
key
=
str
(
int
(
key
))
elif
_skipkeys
:
continue
else
:
...
...
@@ -374,9 +381,11 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
elif
value
is
False
:
yield
'false'
elif
isinstance
(
value
,
int
):
yield
str
(
value
)
# see comment for int/float in _make_iterencode
yield
str
(
int
(
value
))
elif
isinstance
(
value
,
float
):
yield
_floatstr
(
value
)
# see comment for int/float in _make_iterencode
yield
_floatstr
(
float
(
value
))
else
:
if
isinstance
(
value
,
(
list
,
tuple
)):
chunks
=
_iterencode_list
(
value
,
_current_indent_level
)
...
...
@@ -402,9 +411,11 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
elif
o
is
False
:
yield
'false'
elif
isinstance
(
o
,
int
):
yield
str
(
o
)
# see comment for int/float in _make_iterencode
yield
str
(
int
(
o
))
elif
isinstance
(
o
,
float
):
yield
_floatstr
(
o
)
# see comment for int/float in _make_iterencode
yield
_floatstr
(
float
(
o
))
elif
isinstance
(
o
,
(
list
,
tuple
)):
yield
from
_iterencode_list
(
o
,
_current_indent_level
)
elif
isinstance
(
o
,
dict
):
...
...
Lib/test/test_json/test_enum.py
0 → 100644
Dosyayı görüntüle @
a4998a70
from
enum
import
Enum
,
IntEnum
from
test.test_json
import
PyTest
,
CTest
SMALL
=
1
BIG
=
1
<<
32
HUGE
=
1
<<
64
REALLY_HUGE
=
1
<<
96
class
BigNum
(
IntEnum
):
small
=
SMALL
big
=
BIG
huge
=
HUGE
really_huge
=
REALLY_HUGE
E
=
2.718281
PI
=
3.141593
TAU
=
2
*
PI
class
FloatNum
(
float
,
Enum
):
e
=
E
pi
=
PI
tau
=
TAU
class
TestEnum
:
def
test_floats
(
self
):
for
enum
in
FloatNum
:
self
.
assertEqual
(
self
.
dumps
(
enum
),
repr
(
enum
.
value
))
self
.
assertEqual
(
float
(
self
.
dumps
(
enum
)),
enum
)
self
.
assertEqual
(
self
.
loads
(
self
.
dumps
(
enum
)),
enum
)
def
test_ints
(
self
):
for
enum
in
BigNum
:
self
.
assertEqual
(
self
.
dumps
(
enum
),
str
(
enum
.
value
))
self
.
assertEqual
(
int
(
self
.
dumps
(
enum
)),
enum
)
self
.
assertEqual
(
self
.
loads
(
self
.
dumps
(
enum
)),
enum
)
def
test_list
(
self
):
self
.
assertEqual
(
self
.
dumps
(
list
(
BigNum
)),
str
([
SMALL
,
BIG
,
HUGE
,
REALLY_HUGE
]),
)
self
.
assertEqual
(
self
.
dumps
(
list
(
FloatNum
)),
str
([
E
,
PI
,
TAU
]))
def
test_dict_keys
(
self
):
s
,
b
,
h
,
r
=
BigNum
e
,
p
,
t
=
FloatNum
d
=
{
s
:
'tiny'
,
b
:
'large'
,
h
:
'larger'
,
r
:
'largest'
,
e
:
"Euler's number"
,
p
:
'pi'
,
t
:
'tau'
,
}
nd
=
self
.
loads
(
self
.
dumps
(
d
))
self
.
assertEqual
(
nd
[
str
(
SMALL
)],
'tiny'
)
self
.
assertEqual
(
nd
[
str
(
BIG
)],
'large'
)
self
.
assertEqual
(
nd
[
str
(
HUGE
)],
'larger'
)
self
.
assertEqual
(
nd
[
str
(
REALLY_HUGE
)],
'largest'
)
self
.
assertEqual
(
nd
[
repr
(
E
)],
"Euler's number"
)
self
.
assertEqual
(
nd
[
repr
(
PI
)],
'pi'
)
self
.
assertEqual
(
nd
[
repr
(
TAU
)],
'tau'
)
def
test_dict_values
(
self
):
d
=
dict
(
tiny
=
BigNum
.
small
,
large
=
BigNum
.
big
,
larger
=
BigNum
.
huge
,
largest
=
BigNum
.
really_huge
,
e
=
FloatNum
.
e
,
pi
=
FloatNum
.
pi
,
tau
=
FloatNum
.
tau
,
)
nd
=
self
.
loads
(
self
.
dumps
(
d
))
self
.
assertEqual
(
nd
[
'tiny'
],
SMALL
)
self
.
assertEqual
(
nd
[
'large'
],
BIG
)
self
.
assertEqual
(
nd
[
'larger'
],
HUGE
)
self
.
assertEqual
(
nd
[
'largest'
],
REALLY_HUGE
)
self
.
assertEqual
(
nd
[
'e'
],
E
)
self
.
assertEqual
(
nd
[
'pi'
],
PI
)
self
.
assertEqual
(
nd
[
'tau'
],
TAU
)
class
TestPyEnum
(
TestEnum
,
PyTest
):
pass
class
TestCEnum
(
TestEnum
,
CTest
):
pass
Modules/_json.c
Dosyayı görüntüle @
a4998a70
...
...
@@ -116,6 +116,8 @@ raise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
static
PyObject
*
encoder_encode_string
(
PyEncoderObject
*
s
,
PyObject
*
obj
);
static
PyObject
*
encoder_encode_long
(
PyEncoderObject
*
s
UNUSED
,
PyObject
*
obj
);
static
PyObject
*
encoder_encode_float
(
PyEncoderObject
*
s
,
PyObject
*
obj
);
#define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
...
...
@@ -1301,14 +1303,46 @@ _encoded_const(PyObject *obj)
}
}
static
PyObject
*
encoder_encode_long
(
PyEncoderObject
*
s
UNUSED
,
PyObject
*
obj
)
{
/* Return the JSON representation of a PyLong and PyLong subclasses.
Calls int() on PyLong subclasses in case the str() was changed.
Added specifically to deal with IntEnum. See Issue18264. */
PyObject
*
encoded
,
*
longobj
;
if
(
PyLong_CheckExact
(
obj
))
{
encoded
=
PyObject_Str
(
obj
);
}
else
{
longobj
=
PyNumber_Long
(
obj
);
if
(
longobj
==
NULL
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Unable to coerce int subclass to int"
);
return
NULL
;
}
encoded
=
PyObject_Str
(
longobj
);
Py_DECREF
(
longobj
);
}
return
encoded
;
}
static
PyObject
*
encoder_encode_float
(
PyEncoderObject
*
s
,
PyObject
*
obj
)
{
/* Return the JSON representation of a PyFloat */
/* Return the JSON representation of a PyFloat.
Modified to call float() on float subclasses in case the subclass
changes the repr. See Issue18264. */
PyObject
*
encoded
,
*
floatobj
;
double
i
=
PyFloat_AS_DOUBLE
(
obj
);
if
(
!
Py_IS_FINITE
(
i
))
{
if
(
!
s
->
allow_nan
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Out of range float values are not JSON compliant"
);
PyErr_SetString
(
PyExc_ValueError
,
"Out of range float values are not JSON compliant"
);
return
NULL
;
}
if
(
i
>
0
)
{
...
...
@@ -1321,8 +1355,24 @@ encoder_encode_float(PyEncoderObject *s, PyObject *obj)
return
PyUnicode_FromString
(
"NaN"
);
}
}
/* Use a better float format here? */
return
PyObject_Repr
(
obj
);
/* coerce float subclasses to float (primarily for Enum) */
if
(
PyFloat_CheckExact
(
obj
))
{
/* Use a better float format here? */
encoded
=
PyObject_Repr
(
obj
);
}
else
{
floatobj
=
PyNumber_Float
(
obj
);
if
(
floatobj
==
NULL
)
{
PyErr_SetString
(
PyExc_ValueError
,
"Unable to coerce float subclass to float"
);
return
NULL
;
}
encoded
=
PyObject_Repr
(
floatobj
);
Py_DECREF
(
floatobj
);
}
return
encoded
;
}
static
PyObject
*
...
...
@@ -1366,7 +1416,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
return
_steal_accumulate
(
acc
,
encoded
);
}
else
if
(
PyLong_Check
(
obj
))
{
PyObject
*
encoded
=
PyObject_Str
(
obj
);
PyObject
*
encoded
=
encoder_encode_long
(
s
,
obj
);
if
(
encoded
==
NULL
)
return
-
1
;
return
_steal_accumulate
(
acc
,
encoded
);
...
...
@@ -1551,9 +1601,10 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
goto
bail
;
}
else
if
(
PyLong_Check
(
key
))
{
kstr
=
PyObject_Str
(
key
);
if
(
kstr
==
NULL
)
kstr
=
encoder_encode_long
(
s
,
key
);
if
(
kstr
==
NULL
)
{
goto
bail
;
}
}
else
if
(
skipkeys
)
{
Py_DECREF
(
item
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment