【问题标题】:Uploading JSON to Bigquery unspecific error将 JSON 上传到 Bigquery 未指定错误
【发布时间】:2018-11-02 03:37:55
【问题描述】:

在短暂尝试 (https://github.com/pydata/pandas-gbq) 并意识到 pandas-gbq 不支持 RECORD 类型,即没有嵌套字段后,我才刚刚开始使用 python BigQuery API (https://github.com/GoogleCloudPlatform/google-cloud-python/tree/master/bigquery)。

现在我正在尝试将嵌套数据上传到 BigQuery。我设法使用相应的架构创建了表,但是我正在努力上传 json 数据。

from google.cloud import bigquery
from google.cloud.bigquery import Dataset
from google.cloud.bigquery import LoadJobConfig
from google.cloud.bigquery import SchemaField

SCHEMA = [
    SchemaField('full_name', 'STRING', mode='required'),
    SchemaField('age', 'INTEGER', mode='required'),
    SchemaField('address', 'RECORD', mode='REPEATED', fields=(
        SchemaField('test', 'STRING', mode='NULLABLE'),
        SchemaField('second','STRING', mode='NULLABLE')
    ))
]

table_ref = client.dataset('TestApartments').table('Test2')

table = bigquery.Table(table_ref, schema=SCHEMA)
table = client.create_table(table)

当尝试将一个非常简单的 JSON 上传到 bigquery 时,我得到一个相当模糊的错误

400 读取数据时出错,错误信息:遇到 JSON 表 错误太多,放弃。行数:1;错误:1.请查看 错误流以获取更多详细信息。

除了它放弃我让我有点难过之外,显然错误描述并没有真正帮助...... 请在下面找到我如何尝试上传 JSON 和示例数据。

job_config = bigquery.LoadJobConfig()
job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON

with open('testjson.json', 'rb') as source_file:
    job = client.load_table_from_file(
        source_file,
        table_ref,
        location='US',  # Must match the destination dataset location.
        job_config=job_config)  # API request

job.result()  # Waits for table load to complete.

print('Loaded {} rows into {}:{}.'.format(
    job.output_rows, dataset_id, table_id))

这是我的 JSON 对象

"[{'full_name':'test','age':2,'address':[{'test':'hi','second':'hi2'}]}]"

如果我没记错的话,这似乎是上传嵌套数据的唯一方法。

【问题讨论】:

    标签: python json google-bigquery


    【解决方案1】:

    我一直在使用您共享的相同代码和 JSON 内容重现您的场景,我怀疑问题只是您在引号之间定义 JSON 内容("'),而它应该没有那种格式。

    正确的格式是@ElliottBrossard 在他的回答中已经与您分享的格式:

    {'full_name':'test', 'age':2, 'address': [{'test':'hi', 'second':'hi2'}]}
    

    如果我使用 testjson.json 文件中的内容运行您的代码,我会收到响应 Loaded 1 rows into MY_DATASET:MY_TABLE 并且内容会加载到表中。否则,如果我使用下面的格式(您根据您的问题和其他答案中的 cmets 使用该格式),我会得到结果 google.api_core.exceptions.BadRequest: 400 Error while reading data, error message: JSON table encountered too many errors, giving up. Rows: 1; errors: 1. Please look into the error stream for more details

    "{'full_name':'test','age':2,'address':[{'test':'hi','second':'hi2'}]}"
    

    此外,您可以转到 BigQuery UI 中的“工作”页面(点击链接 https://bigquery.cloud.google.com/jobs/YOUR_PROJECT_ID),您会在其中找到更多信息有关失败的加载作业的信息。例如,当我使用错误的 JSON 格式运行您的代码时,我得到的是:

    正如您将看到的,这里的错误消息更相关:

    error message: JSON parsing error in row starting at position 0: Value encountered without start of object
    

    它表示它找不到任何有效的 JSON 对象的开头(即对象开头的括号{)。

    TL;DR:删除 JSON 对象中的引号,加载作业应该没问题。

    【讨论】:

    • 你是个天才!谢谢@dsesto,非常感谢:D
    • 我很高兴能帮助澄清问题!下次请确保遵循之前答案中的所有步骤,因为@ElliottBrossard 已经在他的答案中发布了正确的 JSON 格式;)
    • 他确实做到了,我从 echo 中复制了部分并专注于括号。无论如何,谢谢你的帮助。任何想法,为什么我的失败工作虽然 python API 没有出现在列表中?
    • 在哪个列表中?他们不是通过the jobs page 获得的吗?
    • 不,它们不是(没有 python 作业出现在那里)。它们在运行 bq ls -j --all 时确实会出现,但在使用 bq show -j [job_id is getting from bq ls -j --all] 显式查询它们时会产生错误
    【解决方案2】:

    我认为你的 JSON 内容应该是:

    {'full_name':'test','age':2,'address':[{'test':'hi','second':'hi2'}]}
    

    (无括号。)以使用命令行客户端为例:

    $ echo "{'full_name':'test','age':2,'address':[{'test':'hi','second':'hi2'}]}" \
        > example.json
    $ bq query --use_legacy_sql=false \
        "CREATE TABLE tmp_elliottb.JsonExample (full_name STRING NOT NULL, age INT64 NOT NULL, address ARRAY<STRUCT<test STRING, second STRING>>);"
    $ bq load --source_format=NEWLINE_DELIMITED_JSON \
        tmp_elliottb.JsonExample example.json
    $ bq head tmp_elliottb.JsonExample
    +-----------+-----+--------------------------------+
    | full_name | age |            address             |
    +-----------+-----+--------------------------------+
    | test      |   2 | [{"test":"hi","second":"hi2"}] |
    +-----------+-----+--------------------------------+
    

    【讨论】:

    • 感谢您的回复,我尝试了您的建议,并不断遇到同样的错误。我尝试了各种引号(即“和')排列无济于事。真的很奇怪......
    • 你去掉了括号?并将每个 JSON 对象放在单独的行上?
    • 确实做到了,目前这真的只是一个测试 JSON 对象,因为我想让原型在移动到真实数据之前工作。我试过:"{'full_name':'test','age':2,'address':[{'test':'hi','second':'hi2'}]}" 以及 '{" full_name":"test","age":2,"address":[{"test":"hi","second":"hi2"}]}' 甚至添加了一个 \n 来表示好的度量 '{" full_name":"test","age":2,"address":[{"test":"hi","second":"hi2"}]}\n' 并尝试了这个。
    • 检查作业信息以查看实际错误是什么...如果您有作业 ID,请使用 bq 命令行并运行 bq show -j &lt;job_id&gt;。您还可以使用bq ls -j 列出最近的工作。也有一种方法可以从 Python 客户端查看加载错误,但我不知道从哪里看出来。
    • 您可以通过-n 选项查看更多职位,例如bq ls -j --all -n 1000 查看 1000 个职位。您也可以执行bq ls -j --all -n 1000 | grep FAILURE 之类的操作来查看失败的。
    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 2020-01-27
    • 2021-12-13
    相关资源
    最近更新 更多