2

I'm trying to send post data to an api which needs to be in json. If the requests header doesn't have Content-type: application-json the request fails and I get an HTTPError: 415 Client Error: Unsupported Media Type for url

However requests only seems to add in this header if I use the inbuilt json parser. Even though the docs seem to suggest the below is equivalent:

>>> r = requests.post(url, data=json.dumps(payload))

>>> r = requests.post(url, json=payload)

Which means that I need to use the built in json parser (or manually add the Content-type header).

However my post data has several Decimal fields (from api converted via json.loads(response.text, parse_float=decimal.Decimal) to be saved in a django DecimalField) which when using the inbuilt requests parser gives the error:

TypeError: Decimal('1560.35') is not JSON serialisable

Is there a way I can use a different json parser with requests (e.g. simplejson which deals with decimals) and have the content-type still specified.

Yunti
  • 6,761
  • 12
  • 61
  • 106

3 Answers3

2

Decimals can be serialized by passing through a custom function.

def decimal_default(obj):
    if isinstance(obj, Decimal):
        return str(obj)
    raise TypeError


data = json.dumps(payload, default=decimal_default)

response = requests.post(
    url=url,
    data=data,
    headers={
        'Content-type': 'application/json',
    }
)
pymarco
  • 7,807
  • 4
  • 29
  • 40
2

Just install simplejson and requests will use it to serialize Decimals:

$ pip3 install simplejson    

This won't raise a TypeError anymore:

>>> requests.post(url, json={'foo': Decimal('1.23')})
Max Malysh
  • 29,384
  • 19
  • 111
  • 115
1

I do not know how to use a different json parser, but you can set the header (and so the content-type).

r = requests.post(url, data=json.dumps(payload), headers={'Content-type': 'application/json'})
# or with a session object
s = requests.Session()
s.headers['Content-Type'] = 'application/json'
s.post(url, data=json.dumps(payload))
salomonderossi
  • 2,180
  • 14
  • 20
  • thanks this does work (if I manage to not put a typo in the header(!). Together with http://stackoverflow.com/questions/16957275/python-to-json-serialization-fails-on-decimal – Yunti May 10 '16 at 14:22