【问题标题】:Coding Python to handle JSON array inconsistencies编写 Python 代码来处理 JSON 数组的不一致
【发布时间】:2018-08-17 10:30:18
【问题描述】:

我一直在使用 Python 从 JSON API 抓取和解析数据。具体来说,我正在使用 CTA(芝加哥交通管理局)火车跟踪器 API。

我会定期收到TypeError: string indices must be integers,我追踪到该邮件是存在多个“火车”运行的数组而不是单个“火车”运行的情况。单次运行不在运行数组中。

{'ctatt':
 {'tmst': '2018-03-05T01:59:10',
 'errCd': '0',
 'errNm': None,
 'route': [{'@name': 'g'},
           {'@name': 'y',
            'train': {'rn': '030',
                     .....
                      'heading': '302'},
           {'@name': 'blue',
            'train': [{'rn': '125',
                     .....
                       'heading': '302'},
                      {'rn': '127',
                     ..... 
                       'heading': '278'},

“g”路线没有运行实例。 'y' 路线有 1 个运行。

  'train': {'rn':}

“蓝色”路线有多条线路。

  'train': [{'rn': ...},{'rn': ...},{'rn': ...}]

我用来解析的代码处理了缺少运行和多次运行的问题。它以 1 次运行命中 TypeError

for train_rt in trains_data['ctatt']['route']:
    line_name = train_rt['@name']
    if train_rt.get('train', 'None') != 'None':
        for train_run in train_rt['train']:

仅处理不在数组中的单次运行的最佳方法是什么?

2 Yellow Line Runs in Chrome: Dev Tools: Network: Preview

1 Yellow Line Run in Chrome: Dev Tools: Network: Preview

我注意到的一个不一致之处是,如果我查询一条路线,这些路线仍然在一个由 1 条路线组成的数组中。

【问题讨论】:

  • 不能检查type的值到'train'键,然后根据需要处理吗?
  • 旁注:只需使用if 'train' in train_rt:。使用'None' 字符串没有任何优点,还有一个很大的缺点,就是你为什么要使用这样一个特殊的字符串值作为哨兵,这看起来令人困惑。
  • @MartijnPieters 我知道,默认返回是'None',但我添加了该代码试图找出错误。我最初有if train_rt.get('train') != None:,但我确定有更好的方法吗?

标签: python arrays json api jagged-arrays


【解决方案1】:

你有两个选择:

  • 使用isinstance() 显式测试列表或字典
  • 将您的访问权限放入try:...except 并捕获TypeError,然后继续将其视为单个元素。

你选择哪一种并不重要(但can be a performance difference),选择你认为最适合你的代码的风格。

例如,如果您使用了isistance() 测试,您可以在单个元素周围添加一个列表,这样您的其余代码就不必更改:

for train_rt in trains_data['ctatt']['route']:
    line_name = train_rt['@name']

    train_runs = train_rt.get('train', [])
    if not isinstance(train_runs, list):
        # single entry, wrap
        train_runs = [train_runs]

    for train_run in train_runs:
        # ...

请注意,如果缺少'train' 键,则上述代码会再次使用空列表进行规范化。这样可以避免另一个 if 测试,因为现在 for 循环根本不会迭代。

如果您有该 API 的支持联系人,我至少会报告该问题并指出他们的数据结构不一致。

【讨论】:

  • 我在很多代码中看到了'try: ...except',需要仔细阅读。捕捉错误并使我的代码更健壮是我继续做其他事情之前的下一步。
  • 谢谢,顺便说一句!我从该代码中学到了一些我真正喜欢的东西!我现在会联系他们,我知道其他人也认为这不一致。
  • @Neal 是的,你肯定需要学习try/except。在 Python 中,大多数东西都使用鸭子类型(如果它可以执行 X 的操作,那么它就是 X),与大多数语言相比,异常被普遍使用。因此,请求宽恕通常比请求许可更容易——try 一些东西,然后编写处理 except 情况的代码。在这种情况下,我认为 Martijn 的 isinstance 的“跳前看”解决方案可能更干净(正如他所说,任何一个都可以,但他的直觉让他首先这样写......),但 EAFP 经常是正确答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
相关资源
最近更新 更多