【问题标题】:python: how do I parse a stream of json arrays with ijson librarypython:如何使用 ijson 库解析 json 数组流
【发布时间】:2016-03-16 23:35:22
【问题描述】:

传入的数据类似于以下内容:

[{
    "foo": "bar"
}]
[{
    "bar": "baz"
}]
[{
    "baz": "foo"
}]

如您所见,对象数组串在一起。 JSON 风格

ijson 能够处理第一个数组,然后我得到:

ijson.common.JSONError: Additional data

当它击中后续数组时。我该如何解决这个问题?

【问题讨论】:

  • 你的问题不太清楚..如果我没看错,请试试这个..stackoverflow.com/questions/12344332/…
  • 不,您是否注意到 JSON 实际上是无效的 JSON?没有根对象,数组之间也没有逗号 (,)。
  • ahaa 那么为什么我们不能使用正则表达式将其解码为字符串:)
  • 这是一个传入的数据流......你会怎么做?
  • @CarlSagan 数据源是什么?无论如何,如果没有逗号(,)解析这将是一个问题..你能分享更多信息吗?

标签: python arrays json


【解决方案1】:

这是对至少有一个有效的正则表达式替换以将完整字符串转换为有效 json 的问题的第一个切入点。仅当您可以在解析为 json 之前读取完整的输入流时,它才有效。

import re

input = ''
for line in inputStream:
  input = input + line    
# input == '[{"foo": "bar"}][{"bar": "baz"}][{"baz": "foo"}]'

# wrap in [] and put commas between each ][
sanitizedInput = re.sub(r"\]\[", "],[", "[%s]" % input)
# sanitizedInput == '[[{"foo": "bar"}],[{"bar": "baz"}],[{"baz": "foo"}]]'

# then parse sanitizedInput
parsed = json.loads(sanitizedInput)
print parsed #=> [[{u'foo': u'bar'}], [{u'bar': u'baz'}], [{u'baz': u'foo'}]]

注意:由于您将整个内容作为字符串读取,因此您可以使用json 而不是ijson

【讨论】:

  • 我认为这是解决方案的良好开端。我想补充一点,来自 Kafka 的 inputStream 可能是实时的,而变量 input 必须等到它从 Kafka 代理读取所有值。我们可以为每个line 使用sanitizedInput = re.sub(r"\]\[", "],[", "[%s]" % line)。这应该可以解决问题。
  • 每一行是否包含[{"foo": "bar"}]?还是每个都像您的问题一样分为三行?
  • 因为如果每一行都是它自己的数组,你可以单独解析每一行,并将其附加到一个数组中。
  • 是的,我打算提出相同的建议,即可以单独解析每一行。 @CarlSagan 你能给我们更多的细节吗?
【解决方案2】:

您可以使用json.JSONDecoder.raw_decode 遍历字符串。它的文档确实说:

这可用于从结尾可能包含无关数据的字符串中解码 JSON 文档。

以下代码示例假定所有 JSON 值都在一个大字符串中:

def json_elements(string):
    while True:
        try:
            (element, position) = json.JSONDecoder.raw_decode(string)
            yield element
            string = string[position:]
        except ValueError:
            break

为了避免自己处理 raw_decode 并能够逐块解析流,我建议我为此目的制作一个库:streamcat

def json_elements(stream)
    decoder = json.JSONDecoder()
    yield from streamcat.stream_to_iterator(stream, decoder)

这适用于 JSON 值的任何串联,无论它们内部或它们之间使用了多少空白字符。

如果您可以控制输入流的编码方式,您可能需要考虑使用line-delimited JSON,这会使解析更容易。

【讨论】:

    猜你喜欢
    • 2013-11-28
    • 2016-09-08
    • 2019-04-07
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 2014-06-15
    • 2016-03-18
    相关资源
    最近更新 更多