web-dev-qa-db-ja.com

JSONがdictをダンプするとTypeErrorがスローされます:キーは文字列でなければなりません

次のdictjson.dumpsを使用してJSONに変換しようとしています:

 {
     'post_engaged': 36,
     'post_impressions': 491,
     'post_story': 23,
     'comment_count': 6,
     'created_time': '03:02 AM, Sep 30, 2012',
     'message': 'Specialities of Shaktis and Pandavas. \n While having power, why there isn\\u2019t',
     < built - in function id > : '471662059541196',
     'status_type': 'status',
     'likes_count': 22
 } {
     'post_engaged': 24,
     'text': '30 Sept 2012 Avyakt Murlli ( Dual Voice )',
     'post_story': 8,
     'comment_count': 3,
     'link': 'http:\\/\\/www.youtube.com\\/watch?v=VGmFj8g7JFA&feature=youtube_gdata_player',
     'post_impressions': 307,
     'created_time': '03:04 AM, Sep 30, 2012',
     'message': 'Not available',
     < built - in function id > : '529439300404155',
     'status_type': 'video',
     'likes_count': 7
 } {
     'post_engaged': 37,
     'post_impressions': 447,
     'post_story': 22,
     'comment_count': 4,
     'created_time': '03:11 AM, Sep 30, 2012',
     'message': '30-09-12 \\u092a\\u094d\\u0930\\u093e\\u0924:\\u092e\\u0941\\u0930\\u0932\\u0940 \\u0913\\u0',
     < built - in function id > : '471643246209744',
     'status_type': 'status',
     'likes_count': 20
 } {
     'post_engaged': 36,
     'post_impressions': 423,
     'post_story': 22,
     'comment_count': 0,
     'created_time': '03:04 AM, Sep 29, 2012',
     'message': 'Essence: Sweet children, whenever you have time, earn the true income. Staying i',
     < built - in function id > : '471274672913268',
     'status_type': 'status',
     'likes_count': 20
 } {
     'post_engaged': 16,
     'text': 'Essence Of Murli 29-09-2012',
     'post_story': 5,
     'comment_count': 2,
     'link': 'http:\\/\\/www.youtube.com\\/watch?v=i6OgmbRsJpg&feature=youtube_gdata_player',
     'post_impressions': 291,
     'created_time': '03:04 AM, Sep 29, 2012',
     'message': 'Not available',
     < built - in function id > : '213046588825668',
     'status_type': 'video',
     'likes_count': 5
 }

しかし、それは私を

TypeError : keys must be a string

エラーはおそらくkeysのようなdictが原因です。

 <built-in function id>: '213046588825668'

誰かが私をガイドしてくれますか?これらの要素をdictから削除する方法はありますか?

17
Viren Rajput

あなたはこのようにそれをきれいにしようとすることができます:

for key in mydict.keys():
  if type(key) is not str:
    try:
      mydict[str(key)] = mydict[key]
    except:
      try:
        mydict[repr(key)] = mydict[key]
      except:
        pass
    del mydict[key]

これは、文字列ではないキーを文字列に変換しようとします。文字列に変換できなかった、または文字列として表せなかったキーは削除されます。

19
bigblind

上記の受け入れられた答えを変更して、私は任意の深さの辞書を処理する関数を書きました:

def stringify_keys(d):
    """Convert a dict's keys to strings if they are not."""
    for key in d.keys():

        # check inner dict
        if isinstance(d[key], dict):
            value = stringify_keys(d[key])
        else:
            value = d[key]

        # convert nonstring to string if needed
        if not isinstance(key, str):
            try:
                d[str(key)] = value
            except Exception:
                try:
                    d[repr(key)] = value
                except Exception:
                    raise

            # delete old key
            del d[key]
    return d
10
Nolan Conaway

私はこれが古い質問であることを知っており、すでに受け入れられた回答がありますが、残念ながら、受け入れられた回答はまったく間違っています。

ここでの実際の問題は、dictを生成するコードが、リテラル文字列"id"ではなく、組み込みのid関数をキーとして使用することです。したがって、単純で明白なかつ正しいのみ解決策は、このバグをソースで修正することです。dictを生成するコードを確認し、id"id"に置き換えます。

3

多分これは役立つでしょう:

your_dict = {("a", "b"):[1,2,3,4]}
# save
with open("file.json","w") as f:
    f.write(json.dumps(list(your_dict.items())))

# load
with open("file.json","r") as f:
    your_dict = dict([Tuple((Tuple(x[0]), x[1])) for x in json.loads(f.read())])
1
Iván B.

理想的には、JSONでサポートされているデータ型に準拠するようにデータをクリーンアップする必要があります。

シリアル化中にこれらの要素をディクテーションから削除または削除するだけの場合は、 skipkeys argument を使用できます。説明は json.dumpセクション

json.dumps(obj, skipkeys=True)

このソリューションはよりクリーンで、標準ライブラリが誤ったキーを処理できるようにします。

警告:このような抜本的な方法を使用すると、JSONキーなどの非準拠データ型のデータが失われるため、その影響を完全に理解する必要があります

0
rite2hhh