【问题标题】:UUID('...') is not JSON serializableUUID('...') 不是 JSON 可序列化的
【发布时间】:2016-08-03 22:37:30
【问题描述】:

当我尝试将 UUID 属性传递给 url 参数时出现此错误。

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

模型.py

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

有什么建议吗?

【问题讨论】:

  • 如果你能告诉我们你是如何通过的以及ClinicHistoryDetail在做什么会更好。

标签: python django uuid


【解决方案1】:

在 Django 上有一个关于这个问题的错误票,但是 python 文档的一个自定义的所谓的“复杂编码器”可以帮助你。

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)

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

json.dumps(my_object, cls=UUIDEncoder)

你的 uuid 字段应该被编码。

【讨论】:

  • json.dumps(my_object.__dict__, cls=UUIDEncoder) 正在工作
  • 难道没有办法获取字符串 uuid、调用 toString 或其他方法吗?
  • 这会去除连字符并更改值。投反对票!
  • @mmla 试试u = UUID(obj.hex) 你会发现它没有任何改变。
  • 如果要保留连字符,可以使用str(obj) 代替obj.hex
【解决方案2】:

将 UUID 转换为字符串。

uuid_str = str(uuid_item)

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 您可能仍然会遇到错误,因为 UUID 或十六进制都不是可序列化的对象。您应该在您的 kwargs 字典 str(object.id)str(object.id.hex) 中将它们设为字符串,然后确保您的正则表达式与您选择的选项匹配。如果是十六进制,请使用[0-9a-f]{32}。否则,使用[A-Za-z0-9\-]+
    【解决方案4】:

    我为此使用了转换功能,它简单干净。

    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)
    

    【讨论】:

      【解决方案5】:

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

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

      详情here

      【讨论】:

        【解决方案6】:

        我想打印出用于调试的数据库模型中的 UUID 字段也有同样的问题。我发现pprint 模块中的pprint() 函数可以处理这个问题。你也可以给它一个indent 参数以获得与json.dumps() 相同的缩进输出

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

        例子:

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

        【讨论】:

          猜你喜欢
          • 2015-03-03
          • 2013-04-26
          • 1970-01-01
          • 2015-01-07
          • 2019-07-05
          • 1970-01-01
          • 2017-10-24
          • 2016-09-19
          • 2016-08-02
          相关资源
          最近更新 更多