Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 读取Amazon Kinesis Firehose stream写入s3的数据_Json_Amazon S3_Amazon Kinesis_Amazon Kinesis Firehose - Fatal编程技术网

Json 读取Amazon Kinesis Firehose stream写入s3的数据

Json 读取Amazon Kinesis Firehose stream写入s3的数据,json,amazon-s3,amazon-kinesis,amazon-kinesis-firehose,Json,Amazon S3,Amazon Kinesis,Amazon Kinesis Firehose,我正在向Kinesis Firehose流写入记录,最终由Amazon Kinesis Firehose写入S3文件 我的记录对象看起来像 ItemPurchase { String personId, String itemId } 写入S3的数据如下所示: {"personId":"p-111","itemId":"i-111"}{"personId":"p-222","itemId":"i-222"}{"personId":"p-333","itemId":"i-333"

我正在向Kinesis Firehose流写入记录,最终由Amazon Kinesis Firehose写入S3文件

我的记录对象看起来像

ItemPurchase {
    String personId,
    String itemId
}
写入S3的数据如下所示:

{"personId":"p-111","itemId":"i-111"}{"personId":"p-222","itemId":"i-222"}{"personId":"p-333","itemId":"i-333"}
没有逗号分隔

在Json数组中没有起始括号

[
]
在Json数组中没有结束括号

[
]
我想读取此数据以获取ItemPurchase对象的列表

List<ItemPurchase> purchases = getPurchasesFromS3(IOUtils.toString(s3ObjectContent))
List purchases=getPurchasesFromS3(IOUtils.toString(s3ObjectContent))

读取此数据的正确方法是什么?

如果有方法更改写入数据的方式,请用一行分隔所有记录。这样,您就可以简单地逐行读取数据。如果没有,那么只需构建一个以“}”为分隔符的scanner对象,并使用scanner进行读取。那就行了。

我也遇到过同样的问题

如果AWS允许我们设置分隔符会更好,但我们可以自己设置

在我的用例中,我一直在收听推特流,一旦收到一条新推特,我立即将其放到
Firehose

当然,这会导致无法解析的单行文件

因此,为了解决这个问题,我将tweet的JSON与
\n
连接起来。 这反过来让我可以使用一些包,在读取流内容时可以输出行,并且可以轻松地解析文件


希望这对你有帮助。

我也有同样的问题,下面是我如何解决的

  • 将“}{”替换为“}\n{”
  • 行被“\n”分割


  • 一个嵌套的json对象有几个“}”,所以按“}”分割行并不能解决问题

    我认为解决这个问题的最佳方法是首先创建一个格式正确的json文件,其中包含分离良好的json对象。在我的例子中,我在推到消防水龙带的事件中添加了“,”。然后,在s3中保存一个文件后,所有文件都将包含json对象,对象之间用一些分隔符分隔(在本例中为逗号)。必须添加的另一项内容是文件开头和结尾的“[”和“]”。然后就有了一个包含多个json对象的正确json文件。现在就可以解析它们了

    Amazon Firehose以这种方式将JSON消息转储到S3,并且不允许您设置分隔符或任何东西,这让我感到不可思议

    最终,我发现解决这个问题的诀窍是使用JSON raw_解码方法处理文本文件

    这将允许您读取一组连接的JSON记录,而不在它们之间使用任何分隔符

    Python代码:

    import json
    
    decoder = json.JSONDecoder()
    
    with open('giant_kinesis_s3_text_file_with_concatenated_json_blobs.txt', 'r') as content_file:
    
        content = content_file.read()
    
        content_length = len(content)
        decode_index = 0
    
        while decode_index < content_length:
            try:
                obj, decode_index = decoder.raw_decode(content, decode_index)
                print("File index:", decode_index)
                print(obj)
            except JSONDecodeError as e:
                print("JSONDecodeError:", e)
                # Scan forward and keep trying to decode
                decode_index += 1
    
    导入json
    decoder=json.JSONDecoder()
    以open('giant_-kinisis_-s3_-text_-file_,带有连接的_-json_-blobs.txt,'r')作为内容文件:
    content=content\u file.read()
    内容长度=长度(内容)
    解码索引=0
    解码索引<内容长度时:
    尝试:
    对象,解码索引=解码器。原始解码(内容,解码索引)
    打印(“文件索引:”,解码索引)
    打印(obj)
    除了JSONDecodeError作为e:
    打印(“JSONDecodeError:,e)
    #向前扫描并继续尝试解码
    解码索引+=1
    
    您可以通过计算括号找到每个有效JSON的名称。假设文件以
    {
    开头,此python代码段应该可以工作:

    导入json
    def read_块(流):
    开括号=0
    块=“”
    尽管如此:
    c=流。读取(1)
    如果不是c:
    打破
    如果c=='{':
    开括号+=1
    elif c=='}':
    开括号-=1
    块+=c
    如果开括号==0:
    屈服块
    块=“”
    如果名称=“\uuuuu main\uuuuuuuu”:
    c=0
    打开('firehose\u json\u blob','r')作为f:
    对于读取块(f)中的块:
    record=json.loads(块)
    打印(记录)
    
    如果firehose的输入源是一个分析应用程序,那么这个不带分隔符的连接JSON是一个众所周知的问题。您应该有一个lambda函数,可以输出多行JSON对象。

    使用这个简单的Python代码

    input_str = '''{"personId":"p-111","itemId":"i-111"}{"personId":"p-222","itemId":"i-222"}{"personId":"p-333","itemId":"i-333"}'''
    
    data_str = "[{}]".format(input_str.replace("}{","},{"))
    data_json = json.loads(data_str)
    
    然后(如果你想)变成熊猫

    import pandas as pd   
    df = pd.DataFrame().from_records(data_json)
    print(df)
    
    这就是结果

    itemId personId
    0  i-111    p-111
    1  i-222    p-222
    2  i-333    p-333
    

    我使用转换Lambda在每条记录的末尾添加一个换行符

    def lambda_handler(event, context):
        output = []
    
        for record in event['records']:
    
            # Decode from base64 (Firehose records are base64 encoded)
            payload = base64.b64decode(record['data'])
    
            # Read json as utf-8    
            json_string = payload.decode("utf-8")
    
            # Add a line break
            output_json_with_line_break = json_string + "\n"
    
            # Encode the data
            encoded_bytes = base64.b64encode(bytearray(output_json_with_line_break, 'utf-8'))
            encoded_string = str(encoded_bytes, 'utf-8')
    
            # Create a deep copy of the record and append to output with transformed data
            output_record = copy.deepcopy(record)
            output_record['data'] = encoded_string
            output_record['result'] = 'Ok'
    
            output.append(output_record)
    
        print('Successfully processed {} records.'.format(len(event['records'])))
    
        return {'records': output}
    

    我曾考虑过这样做,但我认为如果JSON对象中的一个字符串碰巧包含一个}{,那么这项技术就会失败。如果您遍历每个字符,如果您点击一个(表示输入或离开字符串),则切换一个布尔值,计算您所处对象的级别(看到时递增){在一个字符串外,在一个字符串外看到“递减”),然后考虑对象的结尾,当你的级别计数器再次命中0。分离器<代码> } />代码是有问题的,因为内部字符串可以在其中有JSON:<代码> { \代码>(带有逃逸引号),所以使用<代码> }“作为分隔符要好一点,因为内部字符串不能有quotesTo来构建Eran的答案,我使用了一个负的前瞻来解释
    }{
    出现在字符串末尾的情况:
    re.sub('}{((?![,}]),'}\n{',string)
    警告:这只是一个盲流读取器,因此,如果任何JSON blob包含碰巧包含转义括号的字符串,它将中断。这适用于JSON,但不适用于更复杂的标记,如XML。如果每条记录都是XML文档,则需要对其进行解析,并将根元素包装到新的XML文档和其他类型中封闭元素(我使用了
    )。我目前正试图弄清楚如何以这种方式读取S3。