将Python值转换为JSON可序列化的类型 :param value: 要转换的值 :param datetime_format: 日期时间格式 'iso' - 2024-01-15T14:30:45 (ISO标准,带T) 'space' - 2024-01-15 14:30:45 (空格分隔,更常见) 'auto' - 自动选择
(value, datetime_format='space')
| 510 | |
| 511 | |
| 512 | def convert_value(value, datetime_format='space'): |
| 513 | """ |
| 514 | 将Python值转换为JSON可序列化的类型 |
| 515 | |
| 516 | :param value: 要转换的值 |
| 517 | :param datetime_format: 日期时间格式 |
| 518 | 'iso' - 2024-01-15T14:30:45 (ISO标准,带T) |
| 519 | 'space' - 2024-01-15 14:30:45 (空格分隔,更常见) |
| 520 | 'auto' - 自动选择 |
| 521 | """ |
| 522 | if value is None: |
| 523 | return None |
| 524 | # 处理 bytes 类型(包括 BIT 字段) |
| 525 | if isinstance(value, bytes): |
| 526 | # 1. 尝试判断是否是 BIT 类型 |
| 527 | if len(value) <= 8: # BIT 类型通常不会很长 |
| 528 | try: |
| 529 | # 转换为整数 |
| 530 | int_val = int.from_bytes(value, 'big') |
| 531 | |
| 532 | # 如果是 0 或 1,返回布尔值更直观 |
| 533 | if int_val in (0, 1): |
| 534 | return bool(int_val) |
| 535 | else: |
| 536 | return int_val |
| 537 | except: |
| 538 | # 如果转换失败,尝试解码为字符串 |
| 539 | pass |
| 540 | |
| 541 | # 2. 尝试解码为 UTF-8 字符串 |
| 542 | try: |
| 543 | return value.decode('utf-8') |
| 544 | except UnicodeDecodeError: |
| 545 | # 3. 如果包含非打印字符,返回十六进制 |
| 546 | if any(b < 32 and b not in (9, 10, 13) for b in value): # 非打印字符 |
| 547 | return f"0x{value.hex()}" |
| 548 | else: |
| 549 | # 4. 尝试 Latin-1 解码(不会失败) |
| 550 | return value.decode('latin-1') |
| 551 | |
| 552 | elif isinstance(value, bytearray): |
| 553 | # 处理 bytearray |
| 554 | return convert_value(bytes(value)) |
| 555 | |
| 556 | if isinstance(value, timedelta): |
| 557 | # 将 timedelta 转换为秒数(整数)或字符串 |
| 558 | return str(value) # 或 value.total_seconds() |
| 559 | elif isinstance(value, Decimal): |
| 560 | return float(value) |
| 561 | # 4. 处理 datetime |
| 562 | elif isinstance(value, datetime): |
| 563 | if datetime_format == 'iso': |
| 564 | return value.isoformat() |
| 565 | elif datetime_format == 'space': |
| 566 | return value.strftime('%Y-%m-%d %H:%M:%S') |
| 567 | else: # 'auto' 或其他 |
| 568 | # 自动判断:没有时间部分只显示日期 |
| 569 | if value.hour == 0 and value.minute == 0 and value.second == 0 and value.microsecond == 0: |