Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()

like image 288
comiventor Avatar asked Jan 20 '18 13:01

comiventor


1 Answers

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

like image 185
Vao Tsun Avatar answered Nov 04 '22 01:11

Vao Tsun