Python使用json.dumps遇到的问题

目录

背景描述

问题一:字段是 datetime 格式

解决方案

问题二:字段是 byte 格式

解决方案

问题三:在 json.dumps(row) 后再加“\r\n”, 会发现多了一个"\r".

解决方案


背景描述

要做 data migration 的功能,把 AWS 上一个 site 的 DB 里数据,通过 S3 bucket 作为中转站,搬迁到另一个 site 的 DB 中。

DB 数据导出到文件时,由于各个字段中可能都含有特殊字符,拟通过 json 格式输出到文件中。对select出的每一行的数据使用 json.dumps(row) 时,由于数据格式的问题,遇到各种错误。

python 通过 mysql 查出来的结果,每一行的格式是 tuple。

import mysql.connector
import json

conn = mysql.connector.connect(user=dbuname,
                               passwd=dbpassword,
                               host=dbhost,
                               auth_plugin='mysql_native_password',
                               port=3306,
                               db=dbname)


data = ""
with open("src/dlp_expression", 'w+') as file:
    cur = conn.cursor()
    cur.execute("select * from tb_dlp_expression where license_acct_id = %s" % 101001)
    rows = cur.fetchall()

    if rows:
        for row in rows:
            print(type(row))
            data += json.dumps(row)
            data +="\r\n"
    file.write(data)
    file.close()
    cur.close()

 type(row) 的结果是:

 

问题一:字段是 datetime 格式

上述程序会报这个错误:

TypeError: Object of type datetime is not JSON serializable

此时打印出某一行 row,如下所示:

(10756, 101001, 'a8235ae9-123c-4626-a487-dfbba6b33d4e', 0, '', 0, 0, '', 0, 0, 0, '', 0, 0, 0, '[^\\d\\+\\-](\\d{3}\\s\\d{3}\\s\\d{3})[^\\d\\+\\-]', '123 456 789, 992 123 123', 'N1 
N2 N3', 'RomaniaPhoneNumber', 0, 0, 101001, 101001, datetime.datetime(2021, 2, 10, 7, 41, 19), datetime.datetime(1972, 1, 1, 0, 0))

关键在于最后这两个 datetime 格式的字段值。json.dumps 无法对 datetime 时间格式数据进行转化

解决方案

先把datetime类型的值进行转化,再进行json序列化。

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')

        elif isinstance(obj, datetime.date):
            return obj.strftime("%Y-%m-%d")

        else:
            return json.JSONEncoder.default(self, obj)

data = ""
with open("src/dlp_expression", 'w+') as file:
    cur = conn.cursor()
    cur.execute("select * from tb_dlp_expression where license_acct_id = %s" % 101001)
    rows = cur.fetchall()

    if rows:
        for row in rows:
            data += json.dumps(row, cls=MyEncoder)
            data +="\r\n"
    file.write(data)
    file.close()
    cur.close()

 

问题二:字段是 byte 格式

tb_cobranding 中的字段 base64_content,的数据类型为 MEDIUMBLOB。

MySQL中,BLOB是一个二进制大型对象。

具体有四种类型:TinyBlob(最大 255 字节),Blob(最大 65K 字节),MediumBlob(最大 16M 字节),LongBlob(最大 4G 字节)。

当从 tb_cobranding 中读取数据,并写入文件时,json.dumps(row) 会报这个错误:

TypeError: Object of type bytes is not JSON serializable

解决方案

在 MyEncoder 类中增加对 byte 类型数据的处理。

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')

        elif isinstance(obj, datetime.date):
            return obj.strftime("%Y-%m-%d")

        elif isinstance(obj, bytes):
            return str(obj, encoding='utf-8')

        else:
            return json.JSONEncoder.default(self, obj)

  

问题三:在 json.dumps(row) 后再加“\r\n”, 会发现多了一个"\r".

导出的文件里,每一行对应于 table 中的一行数据。所以结尾是 “\r\n”。

但是,用 notepad++ 显示空格和换行时,如图所示,会多出一个空行。

每一行的结尾是“CR CR LF”。

解决方案

每行后只加 “\n”,不加“\r\n”。

for row in rows:
    data += json.dumps(row, cls=MyEncoder)
    data +="\n"

 

你可能感兴趣的:(遇到的问题,python,json)