質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1637閲覧

JSON形式の文字列を分解してリストに格納したい

Otazoman

総合スコア44

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/11/21 08:46

編集2018/11/22 02:41

実現したいこと

AWSのLambdaにてS3からJSONファイルを取得してDynamoDBに投入する
プログラムを作成しようとしております。その際にS3から取得したJSONを
DynamoDBにputできる形式に変換するところでつまずいております。

理想としては以下の様にリストの中に辞書が入れ子になっている形式が理想なのです。

[{"key1":"val1","key2":"val2"},{"key1":"val3","key2":"val4"},{"key1":"val5","key2":"val6"}]

現在はリストの中に文字列として入ってしまっている状態です。(以下の様な状態です)

["{"key1":"val1","key2":"val2"},{"key1":"val3","key2":"val4"},{"key1":"val5","key2":"val6"}"]

何とか理想通りの出力とするためにはどの様に処理すればいいでしょうか。

該当のソースコード

python

1import logging 2import boto3 3import json 4import datetime 5 6LOGGER = logging.getLogger() 7LOGGER.setLevel(logging.INFO) 8dynamodb = boto3.resource('dynamodb') 9s3 = boto3.client('s3') 10 11# DynamoDBに書込み(ここは動きます) 12def put_item(writeitems,writetable): 13 try: 14 table = dynamodb.Table(writetable) 15 with table.batch_writer() as batch: 16 for i in range(len(writeitems)): 17 batch.put_item( 18 Item=writeitems[i] 19 ) 20 LOGGER.info("Completed registration") 21 return "end" 22 except Exception as e: 23 LOGGER.error(e) 24 raise e 25# S3で読込んだJSONを辞書型配列に変換 26def translateJson(res): 27 try: 28 td = json.dumps(res.decode('utf-8-sig')) 29 tr = str.maketrans({'[': '', ']': ''}) 30 s = td.translate(tr) 31 d = json.loads(s) 32 values = [] 33 values.append(d) 34 35# ここのコメント相当の箇所をS3から読み込んで処理させたいというものです。 36# この書式であれば辞書型なのでうまく処理はできました。 37# for i in range(50): 38# values.append({ 39# 'i-code': '111-0002', 40# 's-key': 'blog' + str(i), 41# 'VAL1': i, 42# }) 43 44 return values 45 except Exception as e: 46 LOGGER.error(e) 47 raise e 48#### 49def lambda_handler(event, context): 50 try: 51 table_name = "item-content" 52 bucket_name = 'dynamodb-importdata' 53 file_name = 'item-content.json' 54 cd = datetime.datetime.now() 55 response = s3.get_object(Bucket=bucket_name, Key=file_name) 56 tabledata = response['Body'].read() 57 objItems = translateJson(tabledata) 58 stat = put_item(objItems,table_name) 59 LOGGER.info("Completed registration") 60 return objItems 61 except Exception as e: 62 LOGGER.error(e) 63 raise e

その他補足

res.decode('utf-8-sig')の時点での文字列です。

"\"[{\\"item-code\\":\\"1-0001\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"2000\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee1\\",\\"VAL3\\":\\"\u8aac\u660e1\\",\\"VAL4\\":\\"\u9805\u76ee1\\",\\"VAL5\\":\\"\u67a01\\"},{\\"item-code\\":\\"1-0002\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"2500\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee2\\",\\"VAL3\\":\\"\u8aac\u660e2\\",\\"VAL4\\":\\"\u9805\u76ee2\\",\\"VAL5\\":\\"\u67a02\\"},{\\"item-code\\":\\"1-0003\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"3000\\",\\"VAL5\\":\\"\u67a03\\"},{\\"item-code\\":\\"7-0011\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"49680\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee64\\",\\"VAL3\\":\\"\u8aac\u660e64\\",\\"VAL4\\":\\"\u9805\u76ee64\\",\\"VAL5\\":\\"\u67a064\\"},{\\"item-code\\":\\"7-0012\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"53320\\",\\"VAL3\\":\\"\u8aac\u660e65\\",\\"VAL4\\":\\"\u9805\u76ee65\\",\\"VAL5\\":\\"\u67a065\\"},{\\"item-code\\":\\"7-0013\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"56960\\",\\"VAL5\\":\\"\u67a066\\"},{\\"item-code\\":\\"7-0014\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"60600\\",\\"VAL5\\":\\"\u67a067\\"},{\\"item-code\\":\\"8-0001\\",\\"search-key\\":\\"1110\\",\\"VAL1\\":\\"64240\\",\\"VAL5\\":\\"\u67a068\\"},{\\"item-code\\":\\"8-0002\\",\\"search-key\\":\\"1110\\",\\"VAL1\\":\\"67880\\",\\"VAL5\\":\\"\u67a069\\"},{\\"item-code\\":\\"8-0003\\",\\"search-key\\":\\"1011\\",\\"VAL1\\":\\"71520\\",\\"VAL3\\":\\"\u8aac\u660e70\\",\\"VAL4\\":\\"\u9805\u76ee70\\",\\"VAL5\\":\\"\u67a070\\"}]\""

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2018/11/21 14:32 編集

res.decode('utf-8-sig')の時点ではどんな文字列になっていますか? translateJsonの返り値を質問文に記載されている希望のフォーマットに変換したいという理解で良いでしょうか
guest

回答1

0

ベストアンサー

二回loadsすると良い具合になるようです。

python

1>>> s = "\"[{\\"item-code\\":\\"1-0001\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"2000\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee1\\",\\"VAL3\\":\\"\u8aac\u660e1\\",\\"VAL4\\":\\"\u9805\u76ee1\\",\\"VAL5\\":\\"\u67a01\\"},{\\"item-code\\":\\"1-0002\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"2500\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee2\\",\\"VAL3\\":\\"\u8aac\u660e2\\",\\"VAL4\\":\\"\u9805\u76ee2\\",\\"VAL5\\":\\"\u67a02\\"},{\\"item-code\\":\\"1-0003\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"3000\\",\\"VAL5\\":\\"\u67a03\\"},{\\"item-code\\":\\"7-0011\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"49680\\",\\"VAL2\\":\\"\u30c6\u30b9\u30c8\u9805\u76ee64\\",\\"VAL3\\":\\"\u8aac\u660e64\\",\\"VAL4\\":\\"\u9805\u76ee64\\",\\"VAL5\\":\\"\u67a064\\"},{\\"item-code\\":\\"7-0012\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"53320\\",\\"VAL3\\":\\"\u8aac\u660e65\\",\\"VAL4\\":\\"\u9805\u76ee65\\",\\"VAL5\\":\\"\u67a065\\"},{\\"item-code\\":\\"7-0013\\",\\"search-key\\":\\"1111\\",\\"VAL1\\":\\"56960\\",\\"VAL5\\":\\"\u67a066\\"},{\\"item-code\\":\\"7-0014\\",\\"search-key\\":\\"1010\\",\\"VAL1\\":\\"60600\\",\\"VAL5\\":\\"\u67a067\\"},{\\"item-code\\":\\"8-0001\\",\\"search-key\\":\\"1110\\",\\"VAL1\\":\\"64240\\",\\"VAL5\\":\\"\u67a068\\"},{\\"item-code\\":\\"8-0002\\",\\"search-key\\":\\"1110\\",\\"VAL1\\":\\"67880\\",\\"VAL5\\":\\"\u67a069\\"},{\\"item-code\\":\\"8-0003\\",\\"search-key\\":\\"1011\\",\\"VAL1\\":\\"71520\\",\\"VAL3\\":\\"\u8aac\u660e70\\",\\"VAL4\\":\\"\u9805\u76ee70\\",\\"VAL5\\":\\"\u67a070\\"}]\"" 2>>> import json 3>>> json.loads(json.loads(s)) 4[{'item-code': '1-0001', 'VAL2': 'テスト項目1', 'VAL4': '項目1', 'VAL3': '説明1', 'VAL5': '枠1', 'search-key': '1010', 'VAL1': '2000'}, {'item-code': '1-0002', 'VAL2': 'テスト項目2', 'VAL4': '項目2', 'VAL3': '説明2', 'VAL5': '枠2', 'search-key': '1010', 'VAL1': '2500'}, {'item-code': '1-0003', 'VAL5': '枠3', 'search-key': '1010', 'VAL1': '3000'}, {'item-code': '7-0011', 'VAL2': 'テスト項目64', 'VAL4': '項目64', 'VAL3': '説明64', 'VAL5': '枠64', 'search-key': '1111', 'VAL1': '49680'}, {'item-code': '7-0012', 'VAL3': '説明65', 'VAL4': '項目65', 'VAL5': '枠65', 'search-key': '1111', 'VAL1': '53320'}, {'item-code': '7-0013', 'VAL5': '枠66', 'search-key': '1111', 'VAL1': '56960'}, {'item-code': '7-0014', 'VAL5': '枠67', 'search-key': '1010', 'VAL1': '60600'}, {'item-code': '8-0001', 'VAL5': '枠68', 'search-key': '1110', 'VAL1': '64240'}, {'item-code': '8-0002', 'VAL5': '枠69', 'search-key': '1110', 'VAL1': '67880'}, {'item-code': '8-0003', 'VAL3': '説明70', 'VAL4': '項目70', 'VAL5': '枠70', 'search-key': '1011', 'VAL1': '71520'}]

確認したいのですが、

  • この「res.decode('utf-8-sig')の時点での文字列」は純粋に「res.decode('utf-8-sig')の時点での文字列」の返り値ですか? それともtdに代入されている値ですか?
  • このあたりの処理の意義がわかりません。

python

1 td = json.dumps(res.decode('utf-8-sig')) 2 tr = str.maketrans({'[': '', ']': ''}) 3 s = td.translate(tr) 4 d = json.loads(s)

res.decode('utf-8-sig')を単にloadsするようにしなかった理由は何でしょうか。

投稿2018/11/22 02:52

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2018/11/22 03:38

>この「res.decode('utf-8-sig')の時点での文字列」は純粋に「res.decode('utf-8-sig')の時点での文字列」の返り値ですか? それともtdに代入されている値ですか? →tdに代入されている値です。 処理の意図としては、ファイルからバイナリで流れてくるデータを UTF-8でデコードしてJSON化してその際にstrになるので前後の「[]」を 取り除いて文字列として返して、その文字列を辞書型に変換してからリストに 挿入するという処理を行おうとしておりました。 json.loadsについてはこれから試してみます。 早速のご回答ありがとうございます。
Otazoman

2018/11/22 04:01

ありがとうございます。以下のコードで意図通りの動作ができました。 大変、助かりました。しかしながら、「json.loads(json.loads(s))」2回でうまく JSON形式に変換されたのかが分かりません。可能であればお教えいただけるとありがたいです。 修正したコード ```python import logging import boto3 import json import datetime LOGGER = logging.getLogger() LOGGER.setLevel(logging.INFO) dynamodb = boto3.resource('dynamodb') s3 = boto3.client('s3') # DynamoDBに書込み def put_item(writeitems,writetable): try: table = dynamodb.Table(writetable) with table.batch_writer() as batch: for i in range(len(writeitems)): batch.put_item( Item=writeitems[i] ) LOGGER.info("Completed registration") return "end" except Exception as e: LOGGER.error(e) raise e # S3で読込んだJSONを辞書型配列に変換 def translateJson(res): try: td = json.dumps(res.decode('utf-8-sig')) s=json.loads(json.loads(td)) return s except Exception as e: LOGGER.error(e) raise e # main def lambda_handler(event, context): try: table_name = "item-content" bucket_name = 'dynamodb-importdata' file_name = 'item-content.json' cd = datetime.datetime.now() response = s3.get_object(Bucket=bucket_name, Key=file_name) tabledata = response['Body'].read() objItem = translateJson(tabledata) stat = put_item(objItem,table_name) LOGGER.info("Completed registration") return "end" except Exception as e: LOGGER.error(e) raise e ```
hayataka2049

2018/11/22 04:03

二回必要になるのはわざわざ json.dumpsをしているからです。 s=json.loads(res.decode('utf-8-sig')) で必要な結果が得られるように思いますが、これだとうまくいかないのでしょうか?
Otazoman

2018/11/22 07:39

すいません。これでうまく動きました。 s=json.loads(res.decode('utf-8-sig')) デバッグ時に別の箇所で起こっていたエラーと勘違いしていたみたいです。 本当にありがとうございました。今後ともpython頑張りたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問