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_timesurvey_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 字段几乎没有格式问题,您可以使用几个 REPLACEs 来修复,如下例所示

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 字符串格式不正确,则无法提取所有值的主要内容,如果未能解决你的问题,请参考以下文章

Bigquery JSON 提取函数

javascript的JSON对象

自动将数据上传到 Google Cloud Storage 和 BigQuery

避免 BigQuery 中 JSON_EXTRACT 函数中的指数表示法

JSON 数组上的 BigQuery Enumerate-like 函数

如何在 Google Cloud Datalab 中使用 Bigquery JSON 函数