Search code examples
pythonexcelpython-2.7salesforcexlrd

"Cannot deserialize instance of string from START_ARRAY value" Salesforce API issue


Trying to create a SF Contact with values from an .xlsx sheet.

I can create a contact if I manually type in a fake email address, lastname and firstname but cannot reference it to a value I have defined from an xlsx sheet. the print commands are working fine and reading the appropriate data I want them to read.

Only been doing Python for 2 weeks now and have already been able to read, write and save data to/from MySQLdb without issue but now running into this issue and not finding much info on this specifically with SalesForce. Any help would be greatly appreciated.

So the full error is:

File "C:\Python27\lib\site-packages\simple_salesforce-0.70-py2.7.egg\simple_salesforce\api.py", line 749, in _exception_handler raise exc_cls(result.url, result.status_code, name, response_content) simple_salesforce.api.SalesforceMalformedRequest: Malformed request https://na48.salesforce.com/services/data/v37.0/sobjects/Contact/. Response content: [{u'errorCode': u'JSON_PARSER_ERROR', u'message': u'Cannot deserialize instance of string from START_ARRAY value [line:1, column:2]'}]

Email = sheet.col_values(1, 1)
Last = sheet.col_values(2, 1)
First = sheet.col_values(3, 1)
print Email
print Last
print First

sf.Contact.create({'LastName' : Last,'FirstName' : First,'Email' : Email})

Okay, Error is fixed but it only creates one contact/case on salesforce which is the last row in the xlsx sheet rather than creating a contact/case for each row in the xlsx. It reads everything for the most part correctly and does in fact create a contact the correct way but only the last row.

Current Code:

for c in range(sheet.ncols):
  for r in range(sheet.nrows):


    Email = sheet.col_values(1,r)[0]
    print Email
    Last = sheet.col_values(2,r)[0]
    print Last
    First = sheet.col_values(3,r)[0]
    print First
    Phone = sheet.col_values(4,r)[0]
    print Phone
    Street = sheet.col_values(5,r)[0]
    print Street
    City = sheet.col_values(6,r)[0]
    print City
    Postal = sheet.col_values(7,r)[0]
    print Postal
    Product = sheet.col_values(8,r)[0]
    print Product
    Store = sheet.col_values(9,r)[0]
    print Store
    SN = sheet.col_values(10,r)[0]
    print SN
    Name = sheet.col_values(3,r)[0]+sheet.col_values(2,r)[0]



sf.Contact.create({'FirstName' : First, 'LastName' : Last, 'Email' : Email, 'Phone' : Phone, 'MailingStreet' : Street, 'MailingCity' : City, 'MailingPostalCode' : Postal})

Solution

  • The error message from the server says

    Cannot deserialize instance of string from START_ARRAY value [line:1, column:2]

    meaning that the server is expecting a field value to be a string, but the request has an array instead.

    Therefore guessing that sheet.col_values() returns an array, you'd want to change it to

    Email = sheet.col_values(1, 1)[0]
    Last  = sheet.col_values(2, 1)[0]
    First = sheet.col_values(3, 1)[0]
    

    Updated for 2nd issue: Indents are significant in python, your create call only happens once because its outside the loop, you need to move it inside the loop, e.g.

    for c in range(sheet.ncols):
      for r in range(sheet.nrows):
        Email = sheet.col_values(1,r)[0]
        print Email
        Last = sheet.col_values(2,r)[0]
        print Last
        First = sheet.col_values(3,r)[0]
        print First
        Phone = sheet.col_values(4,r)[0]
        print Phone
        Street = sheet.col_values(5,r)[0]
        print Street
        City = sheet.col_values(6,r)[0]
        print City
        Postal = sheet.col_values(7,r)[0]
        print Postal
        Product = sheet.col_values(8,r)[0]
        print Product
        Store = sheet.col_values(9,r)[0]
        print Store
        SN = sheet.col_values(10,r)[0]
        print SN
        Name = sheet.col_values(3,r)[0]+sheet.col_values(2,r)[0]
        sf.Contact.create({'FirstName' : First, 'LastName' : Last, 'Email' : Email, 'Phone' : Phone, 'MailingStreet' : Street, 'MailingCity' : City, 'MailingPostalCode' : Postal})