Google-api-python-client: python3 problem: `discovery.build(...).service.users().messages().send(message)` requires bytes obj that is unserializable by `json`

Created on 21 Sep 2016  路  5Comments  路  Source: googleapis/google-api-python-client

First of all, in Python 2 there is no problem.

In trying to send a message with a service instance (as in this example), by

service.users().messages().send('me', message)

it requires message to be in bytes format, which it tries to serialize with json.dumps. However, in Python 3 this is not possible.

To reproduce run this gist in python2 and python3.

I currently don't know what the solution to this would be.

triage me

Most helpful comment

@jonparrott indeed!

This works:

base64.urlsafe_b64encode(message.as_string().encode('utf-8')).decode('utf-8')

All 5 comments

Can you give the full stacktrace?

python new.py --noauth_local_webserver
Traceback (most recent call last):
  File "new.py", line 92, in <module>
    send_message(message)
  File "new.py", line 82, in send_message
    message = service.users().messages().send(userId='me', body=message).execute()
  File "/Users/basnijholt/anaconda/lib/python3.5/site-packages/googleapiclient/discovery.py", line 764, in method
    actual_path_params, actual_query_params, body_value)
  File "/Users/basnijholt/anaconda/lib/python3.5/site-packages/googleapiclient/model.py", line 151, in request
    body_value = self.serialize(body_value)
  File "/Users/basnijholt/anaconda/lib/python3.5/site-packages/googleapiclient/model.py", line 260, in serialize
    return json.dumps(body_value)
  File "/Users/basnijholt/anaconda/lib/python3.5/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/Users/basnijholt/anaconda/lib/python3.5/json/encoder.py", line 198, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Users/basnijholt/anaconda/lib/python3.5/json/encoder.py", line 256, in iterencode
    return _iterencode(o, 0)
  File "/Users/basnijholt/anaconda/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: b'Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PSJ1cy1hc2NpaSIKTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogN2JpdAp0bzogYmFzbmlqaG9sdEBnbWFpbC5jb20KZnJvbTogYmFzbmlqaG9sdEBnbWFpbC5jb20Kc3ViamVjdDogVGVzdAoKVGV4dA==' is not JSON serializable

you can probably just do message = message.decode('utf-8') and be fine.

@jonparrott indeed!

This works:

base64.urlsafe_b64encode(message.as_string().encode('utf-8')).decode('utf-8')

I ran into this as well, and google is erroring for me.

Trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/my/amazing/path", line 36, in _send_message
    message = (self.service.users().messages().send(userId=email, body=body)
  File "/path/to/venv/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/path/to/venv/python3.8/site-packages/googleapiclient/http.py", line 907, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/gmail/v1/users/email%40gmail.com/messages/send?alt=json returned "Bad Request">

Relevant code:

userID = 'my email'
message = MIMEMultipart('alternative')
message['to'] = to
message['from'] = sender
message['subject'] = subject

part1 = MIMEText(message_text, 'plain')
part2 = MIMEText(message_html, 'html')
message.attach(part1)
message.attach(part2)
body = {'raw': base64.urlsafe_b64encode(message.as_string().encode('utf-8')).decode('utf-8')}
self.service.users().messages().send(userId=userID, body=body).execute()
Was this page helpful?
0 / 5 - 0 ratings