Reputation: 7438
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.
Upvotes: 4
Views: 4354
Reputation: 31545
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')})
Upvotes: 4
Reputation: 8195
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',
}
)
Upvotes: 2
Reputation: 2188
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))
Upvotes: 1