BigQuery json 函数 - 如果 json 字符串格式不正确,则无法提取所有值
Posted
技术标签:
【中文标题】BigQuery json 函数 - 如果 json 字符串格式不正确,则无法提取所有值【英文标题】:BigQuery json function - cannot extract all values if json string not well formatted 【发布时间】:2021-09-13 15:05:16 【问题描述】:我在 BigQuery 的一个字段中存储了一个 json 字符串,该字段具有以下结构::
'language': 'Eng', 'date_started': '2021-02-08 16: 56: 55 GMT', 'link_id': '111', 'url_variables': 'touchpoint': 'key': 'touchpoint', 'value': 'phone', 'type': 'url'
, 'interaction_id': 'key': 'interaction_id', 'value': '111', 'type': 'url'
, 'ip_address': None, 'referer': '', 'user_agent': None, 'response_time': 111, 'data_quality': [], 'longitude': '', 'latitude': '', 'country': '', 'city': '', 'region': '', 'postal': '', 'dma': '', 'survey_data': '25': 'id': 25, 'type': 'TEXTBOX', 'question': 'feedback_source', 'section_id': 1, 'shown': False
, '229': 'id': 229, 'type': 'TEXTBOX', 'question': 'recruitment_method', 'section_id': 1, 'shown': False
, '227': 'id': 227, 'type': 'TEXTBOX', 'question': 'meeting_point', 'section_id': 1, 'answer': 'phone', 'shown': True
, '221': 'id': 221, 'type': 'TEXTBOX', 'question': 'interaction_id', 'section_id': 1, 'answer': '222', 'shown': True
, '217': 'id': 217, 'type': 'TEXTBOX', 'question': 'session_id', 'section_id': 1, 'answer': '333', 'shown': True
, '231': 'id': 231, 'type': 'ESSAY', 'question': 'BlaBla question 4', 'section_id': 3, 'answer': 'Bla Bla answer', 'shown': True
, '255': 'id': 255, 'type': 'TEXTBOX', 'question': 'tz_offset', 'section_id': 3, 'answer': '-120', 'shown': True
, '77': 'id': 77, 'type': 'parent', 'question': 'Bla Bla 1', 'section_id': 35, 'options': '10395': 'id': 10395, 'option': 'Neutraal', 'answer': '3'
, 'shown': True
, '250': 'id': 250, 'type': 'RADIO', 'question': 'Bla Bla?', 'section_id': 66, 'original_answer': '1', 'answer': '1', 'answer_id': 10860, 'shown': True
, '251': 'id': 251, 'type': 'RADIO', 'question': 'Bla Bla', 'section_id': 66, 'original_answer': '0', 'answer': '0', 'answer_id': 10863, 'shown': True
我可以通过下面的查询提取一些值,但我无法提取 response_time 或 survey_data 结构中的任何值。 它们总是以 null 的形式出现。
DECLARE resp STRING
DEFAULT "'id': '111', 'contact_id': '', 'status': 'Complete', 'is_test_data': '0', 'date_submitted': '2021-07-08 17: 02: 16 GMT', 'session_id': '111', 'language': 'Eng', 'date_started': '2021-02-08 16: 56: 55 GMT', 'link_id': '111', 'url_variables': 'touchpoint': 'key': 'touchpoint', 'value': 'phone', 'type': 'url' , 'interaction_id': 'key': 'interaction_id', 'value': '111', 'type': 'url' , 'ip_address': None, 'referer': '', 'user_agent': None, 'response_time': 111, 'data_quality': [], 'longitude': '', 'latitude': '', 'country': '', 'city': '', 'region': '', 'postal': '', 'dma': '', 'survey_data': '25': 'id': 25, 'type': 'TEXTBOX', 'question': 'feedback_source', 'section_id': 1, 'shown': False , '229': 'id': 229, 'type': 'TEXTBOX', 'question': 'recruitment_method', 'section_id': 1, 'shown': False , '227': 'id': 227, 'type': 'TEXTBOX', 'question': 'meeting_point', 'section_id': 1, 'answer': 'phone', 'shown': True , '221': 'id': 221, 'type': 'TEXTBOX', 'question': 'interaction_id', 'section_id': 1, 'answer': '222', 'shown': True , '217': 'id': 217, 'type': 'TEXTBOX', 'question': 'session_id', 'section_id': 1, 'answer': '333', 'shown': True , '231': 'id': 231, 'type': 'ESSAY', 'question': 'BlaBla question 4', 'section_id': 3, 'answer': 'Bla Bla answer', 'shown': True , '255': 'id': 255, 'type': 'TEXTBOX', 'question': 'tz_offset', 'section_id': 3, 'answer': '-120', 'shown': True , '77': 'id': 77, 'type': 'parent', 'question': 'Bla Bla 1', 'section_id': 35, 'options': '10395': 'id': 10395, 'option': 'Neutraal', 'answer': '3' , 'shown': True , '250': 'id': 250, 'type': 'RADIO', 'question': 'Bla Bla?', 'section_id': 66, 'original_answer': '1', 'answer': '1', 'answer_id': 10860, 'shown': True , '251': 'id': 251, 'type': 'RADIO', 'question': 'Bla Bla', 'section_id': 66, 'original_answer': '0', 'answer': '0', 'answer_id': 10863, 'shown': True ";
SELECT
JSON_VALUE( resp, '$.url_variables.interaction_id.value') as url_interaction_id_value ,
JSON_VALUE( resp, '$.url_variables.interaction_id.type') as url_interaction_id_type,
JSON_VALUE( resp, '$.language') as language,
JSON_QUERY( resp, '$.response_time') as response_time, -- NOT WORKING
JSON_QUERY( resp, '$.survey_data') as survey_data -- NOT WORKING
我在 CLI 的 bash 中尝试了 jq,它似乎抱怨某些 None 值没有被引用。
问题: 这是否意味着 BigQuery 会尽可能地尝试从 JSON 字符串中提取值,“直到”遇到格式不正确的内容(例如,未加引号的 None 值),然后它就无法进一步解析并返回空值?
注意:在另一个应用程序中,我已经能够在 Python 中解析 json 文件并从 json 字符串中提取值。
【问题讨论】:
【参考方案1】:看起来您的 resp
字段几乎没有格式问题,您可以使用几个 REPLACE
s 来修复,如下例所示
SELECT
JSON_VALUE( resp, '$.url_variables.interaction_id.value') as url_interaction_id_value ,
JSON_VALUE( resp, '$.url_variables.interaction_id.type') as url_interaction_id_type,
JSON_VALUE( resp, '$.language') as language,
JSON_QUERY( resp, '$.response_time') as response_time, -- WORKING NOW
JSON_QUERY( resp, '$.survey_data') as survey_data -- WORKING NOW,
FROM (
SELECT REPLACE(REPLACE(REPLACE(resp, "None,", "'None',"), "True", "true"), "False", "false") as resp
FROM `project.dataset.table`
)
如果应用于您问题中的示例数据 - 现在它可以满足您的所有需求
【讨论】:
谢谢米哈伊尔,实际上是一位同事向我指出了这个方向,但您的答案是第一位的 :-) 是否在任何地方说明了 BigQuery 使用的是哪种 JSON 解析器?知道这一点以在源头生成兼容的 JSON 字符串可能很有用。 (在这种情况下,我们无法控制 JSON 源)以上是关于BigQuery json 函数 - 如果 json 字符串格式不正确,则无法提取所有值的主要内容,如果未能解决你的问题,请参考以下文章
自动将数据上传到 Google Cloud Storage 和 BigQuery
避免 BigQuery 中 JSON_EXTRACT 函数中的指数表示法