supabase / supabase-py

Python Client for Supabase. Query Postgres from Flask, Django, FastAPI. Python user authentication, security policies, edge functions, file storage, and realtime data streaming. Good first issue.
https://supabase.com/docs/reference/python
MIT License
1.7k stars 199 forks source link

Cannot insert a Decimal #967

Open rdong8 opened 2 days ago

rdong8 commented 2 days ago

Bug report

Describe the bug

A clear and concise description of what the bug is.

Attempting to insert a decimal.Decimal results in this error:

TypeError: Object of type Decimal is not JSON serializable"

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

from decimal import Decimal

from supabase import create_async_client

async def main() -> None:
    client = await create_async_client(...)
    await (
        client
        .from_("test")
        .upsert({'percentage': Decimal(0.5)})
        .execute()
    )

asyncio.run(main())

Expected behavior

A clear and concise description of what you expected to happen.

The Decimal is inserted as is done by psycopg2.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

Additional context

Add any other context about the problem here.

webdrakib commented 1 day ago

To address the bug you encountered while attempting to insert a Decimal value into Supabase, it’s essential to ensure that the value is correctly serialized to JSON before being sent. Since the Decimal type is not JSON serializable by default, you will need to convert it to a format that can be serialized, such as a float or a string.

Here’s a revised version of your code to handle this issue:

Updated Code

import asyncio
from decimal import Decimal
from supabase import create_async_client
async def main() -> None:
    client = await create_async_client(...)
    # Convert Decimal to float before inserting
    percentage_value = Decimal(0.5)
    await (
        client
        .from_("test")
        .upsert({'percentage': float(percentage_value)})  # Convert Decimal to float
        .execute()
    )
asyncio.run(main())

Explanation of Changes

  1. Convert Decimal to Float: The Decimal value is converted to a float using float(percentage_value). This ensures that the value can be serialized to JSON without causing a TypeError.
  2. Maintaining Precision: If you need to maintain precision and avoid floating-point arithmetic issues, consider converting the Decimal to a string instead:
    await (
    client
    .from_("test")
    .upsert({'percentage': str(percentage_value)})  # Convert Decimal to string
    .execute()
silentworks commented 1 day ago

Yes converting the decimal to a string or float is the way. The library won't convert every Python type for you so you have to handle that yourself. psycopg supports that because its probably doing some conversion internally for you.