Search code examples
djangopython-3.xpostgresql-9.3infinitydjango-postgresql

store infinity in postgres json via django


I have a list of tuples like below -

[(float.inf, 1.0), (270, 0.9002), (0, 0.0)]

I am looking for a simple serializer/deserializer that helps me store this tuple in a jsonb field in PostgreSQL.

I tried using JSONEncoder().encode(a_math_function) but didn't help.

I am facing the following error while attempting to store the above list in jsonb field -

django.db.utils.DataError: invalid input syntax for type json
LINE 1: ...", "a_math_function", "last_updated") VALUES (1, '[[Infinit...
DETAIL:  Token "Infinity" is invalid.

Note: the field a_math_function is of type JSONField()


Solution

  • t=# select 'Infinity'::float;
      float8
    ----------
     Infinity
    (1 row)
    

    because https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-FLOAT

    In addition to ordinary numeric values, the floating-point types have several special values:

    Infinity

    -Infinity

    NaN

    yet, the json does not have such possible value (unless its string) https://www.json.org/

    value
    string
    number
    object
    array
    true
    false
    null
    

    thus:

    t=# select '{"k":Infinity}'::json;
    ERROR:  invalid input syntax for type json
    LINE 1: select '{"k":Infinity}'::json;
                   ^
    DETAIL:  Token "Infinity" is invalid.
    CONTEXT:  JSON data, line 1: {"k":Infinity...
    Time: 19.059 ms
    

    so it's not the jango or postgres limitation - just Infinity is invalid token, yet 'Infinity' is a valid string. so

    t=# select '{"k":"Infinity"}'::json;
           json
    ------------------
     {"k":"Infinity"}
    (1 row)
    

    works... But Infinity here is "just a word". Of course you can save it as a string, not as numeric value and check every string if it's not equal "Infinity", and if it is - launch your program logic to treat it as real Infinity... But in short - you can't do it, because json specification does not support it... same asyou can't store lets say red #ff0000 as colour in json - only as string, to be caught and processed by your engine...

    update:

    postgres would cast float to text itself on to_json:

    t=# select to_json(sub) from (select 'Infinity'::float) sub;
            to_json
    -----------------------
     {"float8":"Infinity"}
    (1 row)
    

    update

    https://www.postgresql.org/docs/current/static/datatype-json.html

    When converting textual JSON input into jsonb, the primitive types described by RFC 7159 are effectively mapped onto native PostgreSQL types

    ...

    number numeric NaN and infinity values are disallowed