Python 在Google BigQuery中将嵌套的JSON字符串展平到不同的列

Python 在Google BigQuery中将嵌套的JSON字符串展平到不同的列,python,json,pandas,google-bigquery,Python,Json,Pandas,Google Bigquery,我在一个BigQuery表中有一列,如下所示 {"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}} 在GBQ中是否有这样的输出??(基本上将整个柱展平为不同的柱) 比方说 a={“名称”:“名称1”,“上次交付”:{“推送id”:“推送id

我在一个BigQuery表中有一列,如下所示

{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}
在GBQ中是否有这样的输出??(基本上将整个柱展平为不同的柱)

比方说

a={“名称”:“名称1”,“上次交付”:{“推送id”:“推送id1”, “时间”:“时间1”},“会话id”:“会话id1”,“源”:“SDK”, “属性”:{“用户ID”:“u1”}

我曾尝试使用json\u normalize(a)在Python中获得所需的输出,但每次尝试都会出现以下错误

有人知道我怎样才能得到我想要的输出吗。我错过了什么吗


任何帮助都将不胜感激

以下示例适用于BigQuery标准SQL

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}' col
)
SELECT 
  JSON_EXTRACT_SCALAR(col, '$.name') name,
  STRUCT(
    JSON_EXTRACT_SCALAR(col, '$.last_delivered.push_id') AS push_id,
    JSON_EXTRACT_SCALAR(col, '$.last_delivered.time') AS time
  ) last_delivered,
  JSON_EXTRACT_SCALAR(col, '$.session_id') session_id,
  JSON_EXTRACT_SCALAR(col, '$.source') source,
  STRUCT(
    JSON_EXTRACT_SCALAR(col, '$.properties.UserId') AS UserId
  ) properties
FROM `project.dataset.table`   
并按预期/要求生成结果

Row name    last_delivered.push_id  last_delivered.time session_id  source  properties.UserId    
1   name1   push_id1                time1               session_id1 SDK     u1     

我猜测,为什么它不起作用,是因为您的json数据实际上是一个字符串:

from pandas.io.json import json_normalize 

a = '''{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}'''  

df = json_normalize(a)
输出:

AttributeError: 'str' object has no attribute 'values'    
 print(df.to_string())
  last_delivered.push_id last_delivered.time   name properties.UserId   session_id source
0               push_id1               time1  name1                u1  session_id1    SDK
与:

from pandas.io.json import json_normalize 

a = {"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}  

df = json_normalize(a)
输出:

AttributeError: 'str' object has no attribute 'values'    
 print(df.to_string())
  last_delivered.push_id last_delivered.time   name properties.UserId   session_id source
0               push_id1               time1  name1                u1  session_id1    SDK
如果是这种情况,您可以在规范化之前使用
json.loads()

import json
from pandas.io.json import json_normalize

a = '''{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}'''  

data = json.loads(a)
df = json_normalize(data)

我将您的代码复制到Spyder 3.6中,它可以按照您的要求工作:从pandas.io.json导入json_normalize a={“name”:“name1”,“last_delived”:{“push_id”:“push_id1”,“time”:“time1”},“session id”:“session_id1”,“source”:“SDK”,“properties”:{“UserId”:“u1”}b=json_normalize(a)b Out[5]:last_delivered.push_id last_delivered.time。。。会话\u id源0推送\u id 1时间1。。。session_id1 SDK
json_normalize
对我来说很好。我也知道这个解决方案,但我希望列是动态的。假设对于其他行,属性更多,而对于某些行,值更少。我不喜欢这个,因为我觉得它太手工了。好吧,如果什么都不管用的话,这是唯一的解决办法。无论如何,谢谢你:)我已经回答了你现在的问题。如果您有新问题-请将其作为新问题发布,我们将看看是否可以帮助您。同时,至少考虑一下投票的结果。谢谢米哈伊尔。有没有想过在谷歌大查询中是否有可能?…动态扁平化。通常这类事情都是通过您选择的客户端完成的,比如python。如果您希望完全在BQ中完成这项工作,您需要分两步来实现它——首先生成sql文本,然后执行它。我认为这两步方法是可行的——但是由于对bq的json支持有限——这将过于复杂——所以我认为使用客户端方法——是让他的作品变得完美的方法,谢谢伙计!!。。。。但是,我已经缩小了这个问题。假设我们有一个数据框,其中一列有这样的值。loads()只接受单个字符串值。我知道我可以把它保存在for循环中,但问题是数据帧有数百万行……我认为如果我们这样做,将需要很多时间。还有其他的方法吗???我也一直在尝试。只是用10k行测试,保持循环…上帝!这花了大约30分钟。嗯,输出是我所期望的。每天有超过百万行,我想每天都这样做。有了BQ机器的计算能力,我强烈感觉这些机器可以做得更快,只要有可行性。