Python Forum

Full Version: Invalid JSON payload received. Unknown name “”: Root element must be a message."
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi guys,

I am trying to update a Google contact using People API. Unfortunately I am getting an error:

Invalid JSON payload received. Unknown name "": Root element must be a message.

when executing the request.

Anyone has any clue how can I resolve it? The JSON itself seems to be OK because I used https://developers.google.com/people/api...ateContact to test it, got 200 response and the contact was modified.

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request


# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/contacts']

def modifyContact(service, resourceName, JSON):
    print (JSON)
    service.people().updateContact(resourceName=resourceName, updatePersonFields='phoneNumbers', body=JSON).execute()

def buildJSON(phoneNumbers, etag):
    JSON = ""
    for x in range(0, len(phoneNumbers)):
        if phoneNumbers[x].get('type') == 'mobile':
            if phoneNumbers[x].get('value').find('+48') != -1:
                oldNUmber = phoneNumbers[x].get('value')
                newNumber = phoneNumbers[x].get('value')[3:]
                JSON += """
                        {
                            "type": "mobile",
                            "value": "%s"
                        },
                        {
                            "type": "mobile",
                            "value": "%s"
                        },
                        """ % (oldNUmber, newNumber)
            else:
                JSON += """
                        {
                            "type": "mobile",
                            "value": "%s"
                        },
                        """ % (phoneNumbers[x].get('value'))
        else:
            JSON += """
                        {
                          "type": "%s",
                            "value": "%s"
                        },
                    """ % (phoneNumbers[x].get('type'), phoneNumbers[x].get('value'))
    # remove last whitespaces + character which is exceeding comma
    JSON = JSON.rstrip()[:-1]
    JSON = """
              "phoneNumbers": [
                %s
              ],
              "etag": "%s"
            """ % (JSON, etag)
    #print (JSON)
    return JSON

def main():

    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('people', 'v1', credentials=creds)





    # Call the People API
    print('List 10 connection names')
    results = service.people().connections().list(
        resourceName='people/me',
        pageSize=1000,
        personFields='names,phoneNumbers').execute()
    connections = results.get('connections', [])

    for person in connections:
        names = person.get('names', [])
        phoneNumbers = person.get('phoneNumbers', [])
        if names:
            name = names[0].get('givenName')
            if name == "testAPI":
                print(name)
                print (person.get('etag'))
                print (person.get('resourceName'))
                if phoneNumbers:
                    JSON = buildJSON(phoneNumbers, person.get('etag'))
                    modifyContact(service, person.get('resourceName'), JSON)
                    #print (phoneNumbers[x].get('value'))
                print (person)
if __name__ == '__main__':
    main()
Why didn't you use standard Python module json to build json structures, e.g.
import json
json.dumps([{'type': 'mobile', 'value' : 4}, {'type': 'mobile', 'value' : 3}])
Output:
'[{"type": "mobile", "value": 4}, {"type": "mobile", "value": 3}]'
Using json.dumps is more reliable approach; I am not sure about json-structure that you built '{some content}, {some content}', may be valid version would be '[{some content}, {some content}]'.
Thanks scidam for your reply. Would it make any difference for a service if I make a string containing necessary data than using json.dumps? As per my understaning JSON is a simple text format having specific structure and thats it.
(Aug-18-2019, 01:52 PM)hellraiser Wrote: [ -> ]Would it make any difference for a service if I make a string containing necessary data than using json.dumps?
it will make your code better (or at least that particular json-building part of it)
as to your question - show us the JSON that you get. Looking at lines 49-54 I think it's not a valid json. You can use https://jsonlint.com/ to check for yourself
(Aug-18-2019, 01:59 PM)buran Wrote: [ -> ]it will make your code better (or at least that particular json-building part of it)
as to your question - show us the JSON that you get. Looking at lines 49-54 I think it's not a valid json. You can use https://jsonlint.com/ to check for yourself

hi buran,
Thanks for the help and clarifications. I am still learning both python and JSON and I am not sure how could I pass a value (variable) to JSON that I am building using the way showed by scidam:
json.dumps([{'type': 'mobile', 'value' : 4}, {'type': 'mobile', 'value' : 3}])
Anyway, I solved the issue! :)

First of all when I was troubleshooting I've removed the initial/ending brackets from JSON string.

Should be:
    JSON = """{
                  "phoneNumbers": [
                    %s
                  ],
                  "etag": "%s"
              }
            """ % (JSON, etag)
And second, I had to deserialize JSON string with loads()

    return json.loads(JSON)
And now it works like a charm :)

Thanks guys for your help!