【问题标题】:TypeError: Object of type UUID is not JSON serializable [duplicate]TypeError:UUID 类型的对象不是 JSON 可序列化的 [重复]
【发布时间】:2020-10-17 03:33:44
【问题描述】:

我正在构建一个相当大的 JSON 字典,我在其中指定了一些 uuid,如下所示:

import uuid

game['uuid'] = uuid.uuid1()

我收到以下回溯的类型错误。我不确定问题是什么,因为我们可以在 json 对象中包含 UUID

Traceback (most recent call last):
  File "/Users/claycrosby/Desktop/coding/projects/gambling/scraper/sbtesting.py", line 182, in <module>
    game_json = json.dumps(game)
  File "/opt/miniconda3/envs/ds383/lib/python3.8/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/opt/miniconda3/envs/ds383/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/opt/miniconda3/envs/ds383/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/opt/miniconda3/envs/ds383/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type UUID is not JSON serializable
[Finished in 0.5s with exit code 1]
[cmd: ['/opt/miniconda3/envs/ds383/bin/python3', '/Users/claycrosby/Desktop/coding/projects/gambling/scraper/sbtesting.py']]
[dir: /Users/claycrosby/Desktop/coding/projects/gambling/scraper]
[path: /opt/miniconda3/bin:/opt/miniconda3/condabin:/Library/Frameworks/Python.framework/Versions/3.8/bin:/Library/Frameworks/Python.framework/Versions/3.8/bin:/Users/claycrosby/Desktop/coding/programs/pbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin]

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    uuid.UUID 类本身不能进行 JSON 序列化,但对象可以用多种 JSON 兼容格式表示。从help(uuid.UUID) 我们可以看到这些选项(尽管字节需要更多的工作,因为它们也不是 json)。

     |      bytes       the UUID as a 16-byte string (containing the six
     |                  integer fields in big-endian byte order)
     |  
     |      bytes_le    the UUID as a 16-byte string (with time_low, time_mid,
     |                  and time_hi_version in little-endian byte order)
     |  
     |      fields      a tuple of the six integer fields of the UUID,
     |                  which are also available as six individual attributes
     |                  and two derived attributes:
     |  
     |          time_low                the first 32 bits of the UUID
     |          time_mid                the next 16 bits of the UUID
     |          time_hi_version         the next 16 bits of the UUID
     |          clock_seq_hi_variant    the next 8 bits of the UUID
     |          clock_seq_low           the next 8 bits of the UUID
     |          node                    the last 48 bits of the UUID
     |  
     |          time                    the 60-bit timestamp
     |          clock_seq               the 14-bit sequence number
     |  
     |      hex         the UUID as a 32-character hexadecimal string
     |  
     |      int         the UUID as a 128-bit integer
     |  
     |      urn         the UUID as a URN as specified in RFC 4122
    

    例如,如果您的 API 需要 URN,您会

    >>> game = {'uuid': uuid.uuid1().urn}
    >>> game
    {'uuid': 'urn:uuid:56fabaca-0fe6-11eb-9910-c770eddca9e7'}
    >>> json.dumps(game)
    '{"uuid": "urn:uuid:56fabaca-0fe6-11eb-9910-c770eddca9e7"}'
    

    【讨论】:

      【解决方案2】:

      That1Guy 的回答很好。但是,如果您最终不得不在太多地方处理数据以使其序列化,请考虑编写自己的 JSON 序列化器类来为您完成!例如,这是一个将 IPV4Addresses 转换为字符串的方法:

      from json import JSONEncoder, dumps
      
      class TMCSerializer(JSONEncoder):
      
          def default(self, value: Any) -> str:
              """JSON serialization conversion function."""
      
              # If it's an IP, which is not normally
              # serializable, convert to string.
              if isinstance(value, IPv4Address):
                  return str(value)
      
              # Here you can have other handling for your
              # UUIDs, or datetimes, or whatever else you
              # have.
      
              # Otherwise, default to super
              return super(TMCSerializer, self).default(value)
      

      那你这样称呼它:

      json_str = json.dumps(some_dict, cls=TMCSerializer)
      

      【讨论】:

        【解决方案3】:

        将其转换为字符串,而不是使用 uuid.UUID 对象:

        game['uuid'] = str(uuid.uuid1())
        

        【讨论】:

          猜你喜欢
          • 2019-04-04
          • 1970-01-01
          • 1970-01-01
          • 2021-03-11
          • 2021-07-04
          • 2021-12-10
          • 1970-01-01
          • 2021-09-27
          • 2019-09-04
          相关资源
          最近更新 更多