DJeanCar
DJeanCar

Reputation: 1593

UUID('...') is not JSON serializable

I get this error when i try to pass the UUID attribute to url parameter.

urlpatterns = [
    url(r'^historia-clinica/(?P<uuid>[W\d\-]+)/$', ClinicHistoryDetail.as_view(), name='...'),
]

views.py

class ClinicHistoryDetail(...):
     ...
     my_object = MyModel.objects.create(...)
     ...
     return redirect(reverse('namespace:name', kwargs={'uuid' : my_object.id}))

model.py

class MyModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    ...

Any suggestions?

Upvotes: 85

Views: 119006

Answers (9)

Serafim Suhenky
Serafim Suhenky

Reputation: 2160

If you're straggling with django JSONField on your model then the right way to fix it would be

data = models.JSONField(encoder=DjangoJSONEncoder)

Upvotes: 0

bryoncline
bryoncline

Reputation: 57

I used a lambda function to inline str() the object.

import uuid
import json

mydict = {
    "key1":"value1",
    "guid1": uuid.uuid4()
}

myjson = json.dumps(mydict, default=lambda x : str(x))

print(myjson)

Upvotes: 1

Willemoes
Willemoes

Reputation: 6377

An alternative is to use default=str. I leave it for reference:

import uuid
import json

pk = uuid.UUID("04d8d2dc-e81b-4eaa-8883-d1e361a08da8")
o = json.dumps({"pk": pk}, default=str)
print(o)

Outputs:

{"pk": "04d8d2dc-e81b-4eaa-8883-d1e361a08da8"}

Upvotes: 14

Geolimber
Geolimber

Reputation: 193

Looks like this error is no more relevant for django, while using DjangoJSONEncoder. No need to write own custom encoder. Provided by django handles most known serializing problems.

import json
from django.core.serializers.json import DjangoJSONEncoder
 
json.dumps(my_object, cls=DjangoJSONEncoder)

Details here

Upvotes: 19

Henshal B
Henshal B

Reputation: 2002

Convert UUID to str.

uuid_str = str(uuid_item)

Upvotes: 46

Maoz Zadok
Maoz Zadok

Reputation: 5930

I use convert function for this, it is simple and clean.

import json
from uuid import UUID
def uuid_convert(o):
        if isinstance(o, UUID):
            return o.hex

json.dumps(users,indent=4,default=uuid_convert)

Upvotes: 6

user5359531
user5359531

Reputation: 3555

I had this same problem with a UUID field in a database model that I wanted to print out for debugging. I found that the pprint() function from the pprint module can handle this. You can also give it an indent argument to get the same kind of indented output that you would get from json.dumps()

https://docs.python.org/3/library/pprint.html#pprint.pprint

Example:

>>> import uuid
>>> import pprint
>>> import json
>>> x = uuid.UUID('12345678123456781234567812345678')
>>> x
UUID('12345678-1234-5678-1234-567812345678')
>>> print(x)
12345678-1234-5678-1234-567812345678
>>> json.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
...
...
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: UUID('12345678-1234-5678-1234-567812345678') is not JSON serializable
>>> pprint.pprint(x)
UUID('12345678-1234-5678-1234-567812345678')

Upvotes: -1

IVI
IVI

Reputation: 2116

There is a bug ticket on Django regarding this issue however a custom so called 'complex encoder' by python docs can help you.

import json
from uuid import UUID


class UUIDEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, UUID):
            # if the obj is uuid, we simply return the value of uuid
            return obj.hex
        return json.JSONEncoder.default(self, obj)

Now if we did something like this

json.dumps(my_object, cls=UUIDEncoder)

Your uuid field should be encoded.

Upvotes: 97

Jordan Haines
Jordan Haines

Reputation: 216

For using the UUID in a URL like that, you should pass it as a string:

 return redirect(reverse('namespace:name', kwargs={'uuid' : str(object.id)}))

FYI - it looks like WIMs answer is a bit more thorough. Your regex should certainly be tightened up. If you end up using the string representation of the slug, you'll want a regex like this: [A-Za-z0-9\-]+ which allows for alphanumerics and hyphens.

Upvotes: 6

Related Questions