簡體   English   中英

讀取 Amazon Kinesis Firehose 寫入 s3 的數據 stream

[英]Reading the data written to s3 by Amazon Kinesis Firehose stream

我正在將記錄寫入 Kinesis Firehose stream,該記錄最終由 Amazon Kinesis Firehose 寫入 S3 文件。

我的記錄 object 看起來像

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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

這個問題可以用一個 JSON 解析器來解決,該解析器一次從 stream 中消耗一個對象。JSONDecoder 的raw_decode方法公開了這樣一個解析器,但我編寫了一個庫,它可以直接使用一個 -襯墊。

from firehose_sipper import sip

for entry in sip(bucket=..., key=...):
    do_something_with(entry)

我在這篇博文中添加了更多詳細信息

我正在將記錄寫入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))

讀取此數據的正確方法是什么?

在 Spark 中,我們遇到了同樣的問題。 我們正在使用以下內容:

from pyspark.sql.functions import *

@udf
def concatenated_json_to_array(text):
  final = "["
  separator = ""
  
  for part in text.split("}{"):
    final += separator + part
    separator = "}{" if re.search(r':\s*"([^"]|(\\"))*$', final) else "},{"
      
  return final + "]"


def read_concatenated_json(path, schema):
  return (spark.read
          .option("lineSep", None)
          .text(path)
          .withColumn("value", concatenated_json_to_array("value"))
          .withColumn("value", from_json("value", schema))
          .withColumn("value", explode("value"))
          .select("value.*"))  

它的工作原理如下:

  1. 將數據作為每個文件的一個字符串讀取(無分隔符!)
  2. 使用 UDF 引入 JSON 數組並通過引入逗號來拆分 JSON 對象。 注意:小心不要破壞任何帶有}{字符串!
  3. 將帶有架構的 JSON 解析為 DataFrame 字段。
  4. 將數組分解為單獨的行
  5. 將值對象展開為列。

像這樣使用它:

from pyspark.sql.types import *

schema = ArrayType(
  StructType([
    StructField("type", StringType(), True),
    StructField("value", StructType([
      StructField("id", IntegerType(), True),
      StructField("joke", StringType(), True),
      StructField("categories", ArrayType(StringType()), True)  
    ]), True)
  ])
)

path = '/mnt/my_bucket_name/messages/*/*/*/*/'
df = read_concatenated_json(path, schema)

我在這里寫了更多細節和注意事項: Parsing JSON data from S3 (Kinesis) with Spark 不要只是被}{分割,因為它會弄亂你的字符串數據! 例如: { "line": "a\\"r}{t" }

您可以使用以下腳本。

如果流數據大小未超過您設置的緩沖區大小,則 s3 的每個文件都有一對括號([])和逗號。

import base64

print('Loading function')


def lambda_handler(event, context):
    output = []

    for record in event['records']:
        print(record['recordId'])
        payload = base64.b64decode(record['data']).decode('utf-8')+',\n'

        # Do custom processing on the payload here

        output_record = {
            'recordId': record['recordId'],
            'result': 'Ok',
            'data': base64.b64encode(payload.encode('utf-8'))
        }
        output.append(output_record)

    last = len(event['records'])-1
    print('Successfully processed {} records.'.format(len(event['records'])))
    
    start = '['+base64.b64decode(output[0]['data']).decode('utf-8')
    end = base64.b64decode(output[last]['data']).decode('utf-8')+']'
    
    output[0]['data'] = base64.b64encode(start.encode('utf-8'))
    output[last]['data'] = base64.b64encode(end.encode('utf-8'))
    return {'records': output}

使用 JavaScript 正則表達式。

JSON.parse(`[${item.replace(/}\s*{/g, '},{')}]`);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM