Python JSON은 Decimal 객체를 직렬화합니다.


242

나는 Decimal('3.9')객체의 일부를 가지고 있으며 이것을 JSON 문자열로 인코딩하고 싶습니다.{'x': 3.9} . 나는 클라이언트 측의 정밀도에 관심이 없으므로 플로트가 좋습니다.

이것을 직렬화하는 좋은 방법이 있습니까? JSONDecoder는 Decimal 객체를 허용하지 않으며 사전에 float로 변환하면 {'x': 3.8999999999999999}잘못된 결과를 낳으며 대역폭을 크게 낭비하게됩니다.



3.8999999999999999는 3.4 이상입니다. 0.2는 정확한 float 표현이 없습니다.
Jasen

@Jasen 3.89999999999는 3.4보다 약 12.8 % 더 잘못되었습니다. JSON 표준은 구현이 아닌 직렬화 및 표기법에만 관한 것입니다. IEEE754를 사용하는 것은 원시 JSON 사양의 일부가 아니며이를 구현하는 가장 일반적인 방법 일뿐입니다. 정확한 십진 산술 만 사용하는 구현은 완전히 (사실 더 엄격하게) 준수합니다.
hraban

😂 잘못. 아이러니.
hraban

답변:


147

서브 클래 싱은 json.JSONEncoder어떻습니까?

class DecimalEncoder(json.JSONEncoder):
    def _iterencode(self, o, markers=None):
        if isinstance(o, decimal.Decimal):
            # wanted a simple yield str(o) in the next line,
            # but that would mean a yield on the line with super(...),
            # which wouldn't work (see my comment below), so...
            return (str(o) for o in [o])
        return super(DecimalEncoder, self)._iterencode(o, markers)

그런 다음 다음과 같이 사용하십시오.

json.dumps({'x': decimal.Decimal('5.5')}, cls=DecimalEncoder)

그렇습니다. 실제로는 이와 같이 작동하지 않는다는 것을 알았습니다. 그에 따라 편집합니다. (아이디어는하지만, 동일하게 유지됩니다.)
마이클 Marczyk

문제는 DecimalEncoder()._iterencode(decimal.Decimal('3.9')).next()올바른 것을 반환 '3.9'했지만 다른 DecimalEncoder()._iterencode(3.9).next()객체에 '3.899...'쌓일 때만 반환되는 생성기 객체를 반환하는 것이 었습니다 .next(). 발전기 재미있는 사업. 오 잘 ... 지금 일해야합니다.
Michał Marczyk 2009

8
그냥 return (str(o),)대신 할 수 없어 ? [o]요소가 하나 뿐인 목록인데 왜 루프를 반복합니까?
mpen

2
@Mark : return (str(o),)길이 1의 튜플을 반환하는 반면, 응답 코드는 길이 1의 생성기를 반환합니다. iterencode () docs
Abgan

30
이 구현은 더 이상 작동하지 않습니다. 엘리아스 자 마리아 (Elias Zamaria)는 같은 스타일로 작업하는 사람입니다.
piro

223

Simplejson 2.1 이상은 기본적으로 Decimal 유형을 지원합니다.

>>> json.dumps(Decimal('3.9'), use_decimal=True)
'3.9'

참고 use_decimal입니다 True기본적으로 :

def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
    allow_nan=True, cls=None, indent=None, separators=None,
    encoding='utf-8', default=None, use_decimal=True,
    namedtuple_as_object=True, tuple_as_array=True,
    bigint_as_string=False, sort_keys=False, item_sort_key=None,
    for_json=False, ignore_nan=False, **kw):

그래서:

>>> json.dumps(Decimal('3.9'))
'3.9'

이 기능이 표준 라이브러리에 포함되기를 바랍니다.


7
흠, 이것은 Decimal 객체를 float로 변환합니다. 예를 들어, 통화 작업시 정밀도 손실.
Matthew Schinckel

12
@MatthewSchinckel 나는 그렇지 않다고 생각합니다. 실제로 문자열을 만듭니다. 그리고 결과 문자열을 다시 공급 json.loads(s, use_decimal=True)하면 소수점이 반환됩니다. 전체 프로세스에서 플로트가 없습니다. 위의 답변을 수정했습니다. 원본 포스터가 잘되기를 바랍니다.
셰카

1
아하, 나도 use_decimal=True짐을 쓰지 않았다고 생각 합니다.
Matthew

1
나를 위해 json.dumps({'a' : Decimal('3.9')}, use_decimal=True)제공합니다 '{"a": 3.9}'. 목표가 아니 었습니까 '{"a": "3.9"}'?
MrJ

5
simplejson.dumps(decimal.Decimal('2.2'))또한 작동합니다 : 명시 적 없음 use_decimal(simplejson / 3.6.0에서 테스트 됨). 다시로드하는 또 다른 방법은 다음과 같습니다. json.loads(s, parse_float=Decimal)즉, stdlib를 사용하여 읽을 수 있습니다 json(이전 simplejson버전도 지원됨).
jfs

181

Python 2.6.5를 실행하는 웹 서버에서 Michał Marczyk의 답변을 시도했지만 정상적으로 작동했음을 모든 사람에게 알리고 싶습니다. 그러나 Python 2.7로 업그레이드하면 작동이 중지되었습니다. Decimal 객체를 인코딩하는 방법을 생각해 보았습니다. 이것은 내가 생각해 낸 것입니다.

import decimal

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return float(o)
        return super(DecimalEncoder, self).default(o)

파이썬 2.7에 문제가있는 사람이라면 누구나 도움이 될 것입니다. 나는 그것을 테스트했고 잘 작동하는 것 같다. 누군가 내 솔루션의 버그를 발견하거나 더 나은 방법을 찾은 경우 알려주십시오.


4
Python 2.7은 부동 소수점 반올림 규칙을 변경하여 작동합니다. stackoverflow.com/questions/1447287/…
Nelson

2
simplejson (예 : Google App Engine)을 사용할 수없는 사용자에게는이 답변이 Godsend입니다.
Joel Cross

17
정밀도를 보장하기 위해 unicode또는 str대신 사용하십시오 float.
Seppo Erviälä

2
54.3999 ...의 문제는 Python 2.6.x 및 이전 버전에서 중요했습니다. 여기서 문자열로의 변환 부동 소수점은 정기적으로 작동하지 않았지만 str 로의 변환 Decimal은 큰 따옴표 "54.4"가 아닌 문자열로 직렬화되기 때문에 훨씬 잘못 되었습니다. 숫자.
hynekcer 2016 년

1
python3에서 작동
SeanFromIT 2016 년

43

Python 2.7.11, 플라스크 연금술 ( 'db.decimal'유형) 및 Flask Marshmallow ( 'instant'serializer 및 deserializer의 경우)를 사용하는 Flask 앱에서 GET 또는 POST를 수행 할 때 마다이 오류가 발생했습니다. . serializer 및 deserializer가 Decimal 형식을 JSON 식별 가능한 형식으로 변환하지 못했습니다.

"pip install simplejson"을 수행 한 다음

import simplejson as json

시리얼 라이저와 디시리얼라이저가 다시 시작됩니다. 나는 아무것도하지 않았다 ... DEciamls는 '234.00'플로트 형식으로 표시됩니다.


1
가장 쉬운 수정
SMDC

1
이상하게도 가져와야 할 필요는 없습니다 simplejson. 설치 만하면됩니다. 이 답변에서 처음 언급했습니다 .
bsplosion

이것은 나에게 효과가 없으며 Decimal('0.00') is not JSON serializable pip를 통해 설치 한 후에도 여전히 유효 합니다. 이 상황은 마시멜로와 그래 핀을 모두 사용하는 경우입니다. 나머지 API에서 쿼리가 호출되면 마시멜로는 10 진수 필드에 대해 정상적으로 작동합니다. 그러나 graphql을 사용하여 호출하면 is not JSON serializable오류가 발생했습니다.
Roel

환상적인, 뛰어난,
스파이더 맨

완전한! 당신은 쉽게 (Google 시트를 사용하여 내 경우 gspread에) 수정할 수 없습니다 whcih 다른 사람에 의해 쓰여진 모듈을 사용하고있는 상황에서이 작품
happyskeptic

32

GAE 2.7에서 simplejson에서 내장 json으로 전환하려고 시도했으며 소수에 문제가 있습니다. default가 str (o)를 반환하면 _iterencode가 default 결과로 _iterencode를 호출하기 때문에 따옴표가 있었고 float (o)는 후행 0을 제거합니다.

기본값이 float (또는 추가 서식없이 repr을 호출하는 클래스)에서 상속하고 사용자 정의 __repr__ 메소드가있는 클래스의 객체를 반환하면 원하는대로 작동하는 것 같습니다.

import json
from decimal import Decimal

class fakefloat(float):
    def __init__(self, value):
        self._value = value
    def __repr__(self):
        return str(self._value)

def defaultencode(o):
    if isinstance(o, Decimal):
        # Subclass float with custom repr?
        return fakefloat(o)
    raise TypeError(repr(o) + " is not JSON serializable")

json.dumps([10.20, "10.20", Decimal('10.20')], default=defaultencode)
'[10.2, "10.20", 10.20]'

좋은! 이렇게하면 Python에서 소수점을 가장 가까운 부동 소수점 값으로 반올림하지 않고 소수 값이 JSON에서 Javascript 부동 소수점으로 끝나게됩니다.
konrad

3
불행히도 이것은 최근 Python 3에서는 작동하지 않습니다. 이제 모든 float-subclass를 float로 간주하고 repr을 호출하지 않는 빠른 경로 코드가 있습니다.
Antti Haapala

@AnttiHaapala의 예제는 Python 3.6에서 잘 작동합니다.
Cristian Ciupitu

@CristianCiupitu 실제로, 나는 지금 나쁜 행동을 재현 할 수없는 것 같습니다
Antti Haapala

2
이 솔루션은 v3.5.2rc1 이후, 참조 작동이 중지 github.com/python/cpython/commit/...을 . 거기에 float.__repr__(즉 정밀도를 푼다) 하드 코딩하고, fakefloat.__repr__전혀 호출되지 않습니다. fakefloat에 추가 방법이있는 경우 위의 솔루션은 python3에서 3.5.1까지 올바르게 작동합니다 def __float__(self): return self.
myroslav

30

기본 옵션이 누락되었으므로 다음 사람 / 공을 위해 추가 할 것입니다.

Django 1.7.x부터는에서 DjangoJSONEncoder얻을 수 있는 내장 기능 이 있습니다 django.core.serializers.json.

import json
from django.core.serializers.json import DjangoJSONEncoder
from django.forms.models import model_to_dict

model_instance = YourModel.object.first()
model_dict = model_to_dict(model_instance)

json.dumps(model_dict, cls=DjangoJSONEncoder)

프레스토 악장!


이것이 알기 쉽지만 OP는 장고에 대해 묻지 않았습니까?
std''OrgnlDave

4
@ std''OrgnlDave 당신은 100 % 정확합니다. 나는 여기에 어떻게 왔는지 잊어 버렸지 만 검색어에 "django"가 붙어있는이 질문을 봤다. 그것
Javier Buzzi

6
당신은 내 일 저장
gaozhidf

14

내 $ .02!

웹 서버에 대한 수많은 데이터를 직렬화하기 때문에 JSON 인코더를 확장합니다. 좋은 코드가 있습니다. 그것은 당신이 느끼는 거의 모든 데이터 형식으로 쉽게 확장 가능하며 3.9를"thing": 3.9

JSONEncoder_olddefault = json.JSONEncoder.default
def JSONEncoder_newdefault(self, o):
    if isinstance(o, UUID): return str(o)
    if isinstance(o, datetime): return str(o)
    if isinstance(o, time.struct_time): return datetime.fromtimestamp(time.mktime(o))
    if isinstance(o, decimal.Decimal): return str(o)
    return JSONEncoder_olddefault(self, o)
json.JSONEncoder.default = JSONEncoder_newdefault

내 인생을 훨씬 더 쉽게 만듭니다 ...


3
이것은 올바르지 않습니다 : 3.9를로 재현합니다 "thing": "3.9".
글리프

내 하루를 구 해주신 모든 분들께 가장 좋은 해결책은, 저를 구 해주셔서 감사합니다. 저는 10 진수 문자열로 숫자를 저장하기에 충분합니다.
stackdave

@Glyph는 JSON 표준 (몇 가지가 있습니다 ...)을 통해 인용되지 않은 숫자는 배정도 부동 소수점이며 소수점이 아닙니다. 인용하는 것이 호환성을 보장하는 유일한 방법입니다.
std''OrgnlDave

2
이것에 대한 인용이 있습니까? 내가 읽은 모든 사양은 구현에 따라 다릅니다.
글리프

12

3.9정확히 IEEE 수레 표현할 수없는, 그것은 항상 올 것이다 3.8999999999999999, 예를 들면 시도 print repr(3.9) , 여기에 대해 더 자세히 읽을 수 있습니다 :

http://en.wikipedia.org/wiki/Floating_point
http://docs.sun.com/source/806-3568/ncg_goldberg.html

따라서 float을 원하지 않으면 옵션 만 문자열로 보내고 소수 객체를 JSON으로 자동 변환 할 수 있도록하려면 다음과 같이하십시오.

import decimal
from django.utils import simplejson

def json_encode_decimal(obj):
    if isinstance(obj, decimal.Decimal):
        return str(obj)
    raise TypeError(repr(obj) + " is not JSON serializable")

d = decimal.Decimal('3.5')
print simplejson.dumps([d], default=json_encode_decimal)

클라이언트에서 파싱되면 내부적으로 3.9가되지 않지만 3.9는 유효한 JSON float입니다. 즉, json.loads("3.9")작동합니다, 나는 이것을
원합니다

@Anurag 예제에서 repr (o) 대신 repr (obj)을 의미했습니다.
orokusaki

십진수가 아닌 것을 인코딩하려고하면 이것이 죽지 않습니까?
mikemaccana

1
@nailer, 안됩니다, 당신은 시도 할 수 있습니다, 다음 핸들러가 사용되어야한다는 것을
알리기

1
mikez302의 답변을 참조하십시오-Python 2.7 이상에서는 더 이상 적용되지 않습니다.
Joel Cross

9

장고 사용자 :

최근에 TypeError: Decimal('2337.00') is not JSON serializable JSON 인코딩 을 하는 동안 왔습니다.json.dumps(data)

해결책 :

# converts Decimal, Datetime, UUIDs to str for Encoding
from django.core.serializers.json import DjangoJSONEncoder  

json.dumps(response.data, cls=DjangoJSONEncoder)

그러나 이제 Decimal 값은 문자열이되며 이제 다음 parse_float옵션을 사용하여 데이터를 디코딩 할 때 십진 / 부동 값 파서를 명시 적으로 설정할 수 있습니다 json.loads.

import decimal 

data = json.loads(data, parse_float=decimal.Decimal) # default is float(num_str)

8

로부터 JSON 표준 문서 에 링크로 json.org :

JSON은 숫자의 의미를 무시합니다. 모든 프로그래밍 언어에는 다양한 수의 다양한 용량 및 보완, 고정 또는 부동, 이진 또는 십진수가있을 수 있습니다. 다른 프로그래밍 언어 사이의 교환을 어렵게 만들 수 있습니다. 대신 JSON은 사람이 사용하는 숫자의 표현, 즉 일련의 숫자 만 제공합니다. 모든 프로그래밍 언어는 내부 표현에 동의하지 않더라도 숫자 시퀀스를 이해하는 방법을 알고 있습니다. 교환이 가능합니다.

따라서 JSON에서 Decimals를 문자열이 아닌 숫자로 나타내는 것이 실제로 정확합니다. Bellow는 문제에 대한 가능한 해결책입니다.

사용자 정의 JSON 인코더를 정의하십시오.

import json


class CustomJsonEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)
        return super(CustomJsonEncoder, self).default(obj)

그런 다음 데이터를 직렬화 할 때 사용하십시오.

json.dumps(data, cls=CustomJsonEncoder)

다른 답변에 대한 주석에서 언급했듯이 이전 버전의 Python은 부동으로 변환 할 때 표현을 엉망으로 만들 수 있지만 더 이상 그렇지 않습니다.

파이썬에서 소수점을 다시 얻으려면 :

Decimal(str(value))

이 솔루션은 10 진수에 대한 Python 3.0 설명서에서 암시됩니다 .

float에서 Decimal을 만들려면 먼저 문자열로 변환하십시오.


2
이것은로 변환 파이썬 3에서 "고정"하지 않습니다 float 반드시 당신이 진수 표현을 잃게하고 만드는 불일치로 이어집니다. Decimal사용하는 것이 중요 하다면 문자열을 사용하는 것이 좋습니다.
juanpa.arrivillaga

파이썬 3.1 이후로 이것을하는 것이 안전하다고 생각합니다. 정밀도 손실은 산술 연산에서 해로울 수 있지만 JSON 인코딩의 경우 값의 문자열 표시 만 생성하므로 정밀도는 대부분의 사용 사례에 충분합니다. JSON의 모든 것은 이미 문자열이므로 값을 따옴표로 묶으면 JSON 사양을 무시합니다.
Hugo Mota

그 말로, 나는 플로트로 변환하는 것에 대한 우려를 이해합니다. 원하는 디스플레이 문자열을 생성하기 위해 인코더와 함께 사용하는 다른 전략이있을 수 있습니다. 아직도, 나는 인용 된 가치를 창출 할 가치가 있다고 생각하지 않습니다.
Hugo Mota

@HugoMota "JSON의 모든 것은 이미 문자열이므로 값을 따옴표로 묶으면 JSON 사양이 무시됩니다." 아니요 : rfc-editor.org/rfc/rfc8259.txt-JSON 은 텍스트 기반 인코딩 형식이지만 그 안에있는 모든 것이 문자열로 해석되는 것은 아닙니다. 사양은 문자열과 별도로 숫자를 인코딩하는 방법을 정의합니다.
Gunnar Þór Magnússon '

@ GunnarÞórMagnússon "JSON은 텍스트 기반 인코딩 형식"입니다. "모든 것이 문자열입니다"라는 의미입니다. 미리 숫자를 문자열로 변환하면 JSON이 될 때 문자열이되므로 정밀도를 마법으로 유지하지 않습니다. 그리고 사양에 따르면 숫자에는 따옴표가 없습니다. 읽는 동안 정확성을 유지하는 것은 독자의 책임 입니다.
Hugo Mota

6

이것은 우리 수업에서 추출한 것입니다.

class CommonJSONEncoder(json.JSONEncoder):

    """
    Common JSON Encoder
    json.dumps(myString, cls=CommonJSONEncoder)
    """

    def default(self, obj):

        if isinstance(obj, decimal.Decimal):
            return {'type{decimal}': str(obj)}

class CommonJSONDecoder(json.JSONDecoder):

    """
    Common JSON Encoder
    json.loads(myString, cls=CommonJSONEncoder)
    """

    @classmethod
    def object_hook(cls, obj):
        for key in obj:
            if isinstance(key, six.string_types):
                if 'type{decimal}' == key:
                    try:
                        return decimal.Decimal(obj[key])
                    except:
                        pass

    def __init__(self, **kwargs):
        kwargs['object_hook'] = self.object_hook
        super(CommonJSONDecoder, self).__init__(**kwargs)

어느 유닛 테스트를 통과 :

def test_encode_and_decode_decimal(self):
    obj = Decimal('1.11')
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

    obj = {'test': Decimal('1.11')}
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

    obj = {'test': {'abc': Decimal('1.11')}}
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

json.loads(myString, cls=CommonJSONEncoder)의견은json.loads(myString, cls=CommonJSONDecoder)
Can Kavaklıoğlu

obj가 10 진수가 아닌 경우 object_hook에 기본 반환 값이 필요합니다.
Can Kavaklıoğlu

3

요구 사항에 따라 사용자 지정 JSON 인코더를 만들 수 있습니다.

import json
from datetime import datetime, date
from time import time, struct_time, mktime
import decimal

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return str(o)
        if isinstance(o, date):
            return str(o)
        if isinstance(o, decimal.Decimal):
            return float(o)
        if isinstance(o, struct_time):
            return datetime.fromtimestamp(mktime(o))
        # Any other serializer if needed
        return super(CustomJSONEncoder, self).default(o)

디코더는 이렇게 호출 할 수 있습니다.

import json
from decimal import Decimal
json.dumps({'x': Decimal('3.9')}, cls=CustomJSONEncoder)

출력은 다음과 같습니다.

>>'{"x": 3.9}'

굉장 ... 원 스톱 솔루션 (y)에 대한 감사
muhammed 바질

이것은 실제로 작동합니다! 솔루션을 공유해 주셔서 감사합니다
tthreetorch

3

타사 라이브러리를 사용하지 않으려는 사람들을 위해 ... Elias Zamaria의 대답의 문제는 플로팅으로 변환되어 문제가 발생할 수 있다는 것입니다. 예를 들면 다음과 같습니다.

>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 1e-07}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01733}'

JSONEncoder.encode()메소드를 사용하면 달리 리터럴 json 내용을 반환 할 수 있습니다.이 JSONEncoder.default()경우 json 호환 유형 (float 등)을 반환 한 다음 정상적인 방식으로 인코딩됩니다. 문제encode() 는 (일반적으로) 최상위 수준에서만 작동한다는 것입니다. 그러나 약간의 추가 작업 (python 3.x)으로 여전히 사용할 수 있습니다.

import json
from collections.abc import Mapping, Iterable
from decimal import Decimal

class DecimalEncoder(json.JSONEncoder):
    def encode(self, obj):
        if isinstance(obj, Mapping):
            return '{' + ', '.join(f'{self.encode(k)}: {self.encode(v)}' for (k, v) in obj.items()) + '}'
        if isinstance(obj, Iterable) and (not isinstance(obj, str)):
            return '[' + ', '.join(map(self.encode, obj)) + ']'
        if isinstance(obj, Decimal):
            return f'{obj.normalize():f}'  # using normalize() gets rid of trailing 0s, using ':f' prevents scientific notation
        return super().encode(obj)

어느 것이 당신에게줍니다 :

>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 0.0000001}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01734}'

2

stdOrgnlDave 답변을 기반으로 선택적 래퍼로 호출 할 수 있도록이 래퍼를 정의 했으므로 인코더는 프로젝트 내부의 특정 종류에서만 작동합니다. 작업은 코드 내에서 수행되어야하며 "암시 적"보다 명확하기 때문에이 "기본"인코더를 사용하지 않아야한다고 생각하지만이 기능을 사용하면 시간이 절약 될 것입니다. :-)

import time
import json
import decimal
from uuid import UUID
from datetime import datetime

def JSONEncoder_newdefault(kind=['uuid', 'datetime', 'time', 'decimal']):
    '''
    JSON Encoder newdfeault is a wrapper capable of encoding several kinds
    Use it anywhere on your code to make the full system to work with this defaults:
        JSONEncoder_newdefault()  # for everything
        JSONEncoder_newdefault(['decimal'])  # only for Decimal
    '''
    JSONEncoder_olddefault = json.JSONEncoder.default

    def JSONEncoder_wrapped(self, o):
        '''
        json.JSONEncoder.default = JSONEncoder_newdefault
        '''
        if ('uuid' in kind) and isinstance(o, uuid.UUID):
            return str(o)
        if ('datetime' in kind) and isinstance(o, datetime):
            return str(o)
        if ('time' in kind) and isinstance(o, time.struct_time):
            return datetime.fromtimestamp(time.mktime(o))
        if ('decimal' in kind) and isinstance(o, decimal.Decimal):
            return str(o)
        return JSONEncoder_olddefault(self, o)
    json.JSONEncoder.default = JSONEncoder_wrapped

# Example
if __name__ == '__main__':
    JSONEncoder_newdefault()

0

키워드 인수를 requests사용하여 소수를 포함하는 사전을 라이브러리에 json전달하려면 simplejson다음 을 설치하면됩니다 .

$ pip3 install simplejson    
$ python3
>>> import requests
>>> from decimal import Decimal
>>> # This won't error out:
>>> requests.post('https://www.google.com', json={'foo': Decimal('1.23')})

문제의 원인 은 존재하는 경우에만 requests사용 simplejson하고 json설치되지 않은 경우 내장 기능으로 돌아 가기 때문입니다.


-6

이것은 추가하여 수행 할 수 있습니다

    elif isinstance(o, decimal.Decimal):
        yield str(o)

\Lib\json\encoder.py:JSONEncoder._iterencode있지만 더 나은 솔루션을 기대하고있었습니다.


5
위에서 설명한 것처럼 JSONEncoder를 서브 클래 싱 할 수 있습니다. 확립 된 라이브러리의 설치된 Python 파일을 편집하거나 인터프리터 자체가 최후의 수단이어야합니다.
justanr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.