3

I am trying to set up a function as a webhook handler. I am receiving an error when trying to convert the Lambda Event Body into a dictionary that I can access data from.

If it's relevant, I just gave the Lambda funciton its own URL when creating it instead of using API Gateway as a trigger. This seemed to be functioning fine with my test events, but not when I started getting events from the application that is actually sending the webhooks.

Here is what the Lambda event looks like when I print(json.dumps(event)). Some data removed for privacy.

{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/",
    "rawQueryString": "",
    "headers": {
        "content-type": "application/json",
    },
    "requestContext": {
        "routeKey": "$default",
        "stage": "$default",
        "time": "04/Aug/2022:17:16:05 +0000",
        "timeEpoch": 1659633365645
    },
    "body": "{\n    \"siteId\": 123,\n    \"clientId\": \"100000009\",\n    \"clientUniqueId\": 100000009,\n    \"creationDateTime\": \"2018-08-28T06:45:58Z\",\n    \"status\": \"Non-Member\",\n    \"firstName\": \"John\",\n    \"lastName\": \"Smith\",\n    \"email\": \"[email protected]\",\n    \"mobilePhone\": \"8055551234\",\n    \"homePhone\": null,\n    \"workPhone\": null,\n    \"addressLine1\": \"123 ABC Ct\",\n    \"addressLine2\": ,\n    \"city\": \"San Luis Obispo\",\n    \"state\": \"CA\",\n    \"postalCode\": \"93401\",\n    \"country\": \"US\",\n    \"birthDateTime\": \"1989-07-02T00:00:00Z\",\n    \"gender\": \"Male\",\n    \"appointmentGenderPreference\": null,\n    \"firstAppointmentDateTime\": \"2018-08-29T06:45:58Z\",\n    \"referredBy\": null,\n    \"isProspect\": false,\n    \"isCompany\": false,\n    \"isLiabilityReleased\": true,\n    \"liabilityAgreementDateTime\": \"2018-08-29T06:45:58Z\",\n    \"homeLocation\": 1,\n    \"clientNumberOfVisitsAtSite\": 2,\n    \"indexes\": [\n        {\n            \"indexName\": \"LongtermGoal\",\n            \"indexValue\": \"IncreasedFlexibility\"\n        }\n    ],\n    \"sendPromotionalEmails\": true,\n    \"sendScheduleEmails\": true,\n    \"sendAccountEmails\": true,\n    \"sendPromotionalTexts\": false,\n    \"sendScheduleTexts\": false,\n    \"sendAccountTexts\": false,\n    \"creditCardLastFour\": \"1445\",\n    \"creditCardExpDate\": \"2025-06-30T00:00:00Z\",\n    \"directDebitLastFour\": \"7754\",\n    \"notes\": \"Notes about the client.\",\n    \"photoUrl\": \"https://clients.mindbodyonline.com/studios/ACMEYoga/clients/100000009_large.jpg?osv=637136734414821811\",\n    \"previousEmail\": null\n}",
    "isBase64Encoded": false
}

Obviously, the type() of the body is a string, but it errors when trying to convert to a Dict with json.loads().

I suspect this has to do with the whitespace and escaped newline characters, but I got stuck when trying to deal with that.

Here is my code....

import json
import requests
import datetime


def lambda_handler(event, context):

    eventData = json.loads(event["body"])

    today = datetime.date.today()

    headers = {
        "Api-Token": "",
        "Accept": "application/json",
        "Content-Type": "application/json"
    }

    data = {
        "contact": {
            "email": eventData.get("email"),
            "firstName": eventData.get("firstName"),
            "lastName": eventData.get("lastName"),
            "phone": eventData.get("mobilePhone"),
            "fieldValues": [{
                "field": "15",
                "value": today.strftime("%Y-%m-%d")
                },
                {
                "field": 1,
                "value": eventData.get("clientId")
                }
            ]
        }
    }

    sync_contact = requests.post("[URL]", headers=headers, json=data)

    return {
        'statusCode': 200,
        'body': json.dumps(sync_contact.json()),
    }

The Error I receive is:

Expecting value: line 14 column 21 (char 379)
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 18, in lambda_handler
    eventData = json.loads(event['body'])
  File "/var/lang/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/var/lang/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/var/lang/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
1
  • Somehow, the client appears to have generated and sent invalid JSON. Commented Aug 4, 2022 at 18:29

1 Answer 1

1

This error is produced, as the traceback already tells you, that you pass a variable that is None, blankstring or other incompatible datatype into json.loads().

I tried it myself and I get this error:

    ...
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 14 column 21 (char 379)

char 379 is the emtpy char after \"addressLine2\":, means addressLine2's value is empty, which is not allowed.

Sign up to request clarification or add additional context in comments.

3 Comments

thank you for this answer! Considering I can't change the incoming data from the request, would you recommend fixing this issue with a replace() before trying to parse the json?
I added eventData = eventData.replace(": ,", ": \"\",") to handle any instances where values were omitted. Not sure if there's a "better" way, but seems to be working for now. :)
@whatspaulupto No problem, I'm glad that I could help. If you don't mind you could reward that with an accept ;) For the second comment, seems legit to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.