Search code examples
python-3.xaws-lambdaaws-api-gatewayaws-cdk

How to get response field as json instead of string?


I have a GET endpoint deployed using AWS CDK python as lambda function with API Gateway.

def get_all_farms(self, event, context):
    params = event["queryParams"]
    offset = int(params["offset"] or 0)
    max = int(params["max"] or 20)
    result = db.get_all_farms_paginated(offset, max)
    return {
        "error": False,
        "message": "success",
        "farms": json.dumps(result, default=str),
    }

I have this code. This is giving response like:

{
    "error": false,
    "message": "success",
    "farms": "[{\"id\": 2, \"name\": \"Central Grain\", \"address1\": \"1140 W Locust St\", \"address2\": \"\", \"city\": \"Belvidere\", \"state\": \"IL\", \"county\": \"Boone County\", \"latitude\": \"42.2526532\", \"longitude\": \"-88.85798849999999\", \"created_date\": \"2023-09-25 22:35:17\"}, {\"id\": 3, \"name\": \"Central Grain\", \"address1\": \"1140 W Locust St\", \"address2\": \"\", \"city\": \"Belvidere\", \"state\": \"IL\", \"county\": \"Boone County\", \"latitude\": \"42.2526532\", \"longitude\": \"-88.85798849999999\", \"created_date\": \"2023-09-25 22:39:54\"}, {\"id\": 4, \"name\": \"Central Grain\", \"address1\": \"1140 W Locust St\", \"address2\": \"\", \"city\": \"Belvidere\", \"state\": \"IL\", \"county\": \"Boone County\", \"latitude\": \"42.2526532\", \"longitude\": \"-88.85798849999999\", \"created_date\": \"2023-09-25 22:48:46\"}]"
}

I want to get the farms as json instead of string. If I pass the result directly in the response, I get date conversion error. And the fix for that suggests to use json.dumps. I am not sure how to get json response. Please help. Thanks.


CDK code for GET

myfarm_resource.add_method(
    "GET",
    integration=apigateway.LambdaIntegration(
        api_lambda_myfarm,
        proxy=False,
        passthrough_behavior=apigateway.PassthroughBehavior.WHEN_NO_TEMPLATES,
        request_templates={
            "application/json": request_template,
        },
        integration_responses=[
            apigateway.IntegrationResponse(
                status_code="200",
            )
        ],
    ),
    method_responses=[
        apigateway.MethodResponse(
            status_code="200",
        )
    ],
)

Solution

  • not efficient in the slightest but the following will fix the issue:

    'farms': json.loads(json.dumps(result, default=str))}

    Unfortunatly, I have this in a bunch of places despite it requiring serializing and deserializing the returned dictionary twice. What you give back to the lambda agent gets thrown into json.dumps() without the ability to control the encoders (docs here)). So if you want to control the deserialization (in your case specifying default=str to handle the date times) its simpler serialize twice.