UUID('...')不是JSON可序列化的

DJe*_*Car 20 python django uuid

当我尝试将UUID属性传递给url参数时,我收到此错误.

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

views.py

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

model.py

class MyModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    ...
Run Code Online (Sandbox Code Playgroud)

有什么建议?

IVI*_*IVI 27

Django上有一个关于这个问题的错误票,但python docs定制的所谓"复杂编码器"可以帮助你.

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)
Run Code Online (Sandbox Code Playgroud)

现在,如果我们做了这样的事情

json.dumps(my_object, cls=UUIDEncoder)
Run Code Online (Sandbox Code Playgroud)

你的uuid字段应该编码.

  • 如果您想保留连字符,可以使用“str(obj)”代替“obj.hex”。 (3认同)
  • @mmla 尝试 `u = UUID(obj.hex)` 你会发现它不会改变任何东西。 (2认同)

Geo*_*ber 13

看起来这个错误与 django 不再相关,而使用DjangoJSONEncoder. 无需编写自己的自定义编码器。django 提供处理大多数已知的序列化问题。

import json
from django.core.serializers.json import DjangoJSONEncoder
 
json.dumps(my_object, cls=DjangoJSONEncoder)
Run Code Online (Sandbox Code Playgroud)

详细信息在这里


Hen*_*l B 7

将 UUID 转换为 str。

uuid_str = str(uuid_item)

  • 但为什么 json 编码器不这样做呢? (6认同)

Mao*_*dok 6

我为此使用转换函数,它简单干净。

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)
Run Code Online (Sandbox Code Playgroud)


Jor*_*nes 5

要在类似的 URL 中使用 UUID,您应该将其作为字符串传递:

 return redirect(reverse('namespace:name', kwargs={'uuid' : str(object.id)}))
Run Code Online (Sandbox Code Playgroud)

仅供参考 - 看起来 WIM 的回答更彻底一些。您的正则表达式当然应该收紧。如果您最终使用 slug 的字符串表示形式,您将需要一个像这样的正则表达式:[A-Za-z0-9\-]+它允许字母数字和连字符。


Wil*_*oes 5

另一种方法是使用default=str. 我留下来供参考:

import uuid
import json

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

输出:

{"pk": "04d8d2dc-e81b-4eaa-8883-d1e361a08da8"}
Run Code Online (Sandbox Code Playgroud)