Json dumping a dict throws TypeError: keys must be a string

前端 未结 7 1145
余生分开走
余生分开走 2020-12-09 10:20

I am attempting to convert the following dict into JSON using json.dumps:

 {
     \'post_engaged\': 36,
     \'post_impressions\':          


        
相关标签:
7条回答
  • 2020-12-09 10:44

    Maybe this will help:

    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())])
    
    0 讨论(0)
  • 2020-12-09 10:44

    Nolan conaway's answer gives this result for example

    {"b'opening_hours'": {"b'1_from_hour'": 720, "b'1_to_hour'": 1440, "b'1_break_from_hour'": 1440, "b'1_break_to_hour'": 1440, "b'2_from_hour'": 720, "b'2_to_hour'": 1440, "b'2_break_from_hour'": 1440, "b'2_break_to_hour'": 1440, "b'3_from_hour'": 720, "b'3_to_hour'": 1440, "b'3_break_from_hour'": 1440, "b'3_break_to_hour'": 1440, "b'4_from_hour'": 720, "b'4_to_hour'": 1440, "b'4_break_from_hour'": 1440, "b'4_break_to_hour'": 1440, "b'5_from_hour'": 720, "b'5_to_hour'": 1440, "b'5_break_from_hour'": 1440, "b'5_break_to_hour'": 1440, "b'6_from_hour'": 720, "b'6_to_hour'": 1440, "b'6_break_from_hour'": 1440, "b'6_break_to_hour'": 1440, "b'7_from_hour'": 720, "b'7_to_hour'": 1440, "b'7_break_from_hour'": 1440, "b'7_break_to_hour'": 1440}}

    while this amended version

    import time
    import re
    import json
    from phpserialize import *
    
    
    class Helpers:
       def stringify_keys(self,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 = Helpers().stringify_keys(d[key])
            else:
                value = d[key]
            # convert nonstring to string if needed
            if not isinstance(key, str):
                try:
                    d[key.decode("utf-8")] = value
                except Exception:
                    try:
                        d[repr(key)] = value
                    except Exception:
                        raise
    
                # delete old key
                del d[key]
        return d
    

    will give this cleaner version..

    {"opening_hours": {"1_from_hour": 720, "1_to_hour": 1440, "1_break_from_hour": 1440, "1_break_to_hour": 1440, "2_from_hour": 720, "2_to_hour": 1440, "2_break_from_hour": 1440, "2_break_to_hour": 1440, "3_from_hour": 720, "3_to_hour": 1440, "3_break_from_hour": 1440, "3_break_to_hour": 1440, "4_from_hour": 720, "4_to_hour": 1440, "4_break_from_hour": 1440, "4_break_to_hour": 1440, "5_from_hour": 720, "5_to_hour": 1440, "5_break_from_hour": 1440, "5_break_to_hour": 1440, "6_from_hour": 720, "6_to_hour": 1440, "6_break_from_hour": 1440, "6_break_to_hour": 1440, "7_from_hour": 720, "7_to_hour": 1440, "7_break_from_hour": 1440, "7_break_to_hour": 1440}}

    0 讨论(0)
  • 2020-12-09 10:47

    You could try to clean it up like this:

    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]
    

    This will try to convert any key that is not a string into a string. Any key that could not be converted into a string or represented as a string will be deleted.

    0 讨论(0)
  • 2020-12-09 10:57

    Maybe this will help the next guy:

    strjson = json.dumps(str(dic).replace("'",'"'))
    
    0 讨论(0)
  • 2020-12-09 10:58

    Ideally you would want to clean your data so you comply to the data types supported by JSON.

    If you simply want to suppress/ or remove these elements from the dict while serializing, you can use skipkeys argument, description can be found in json.dump section

    If skipkeys is true (default: False), then dict keys that are not of a basic type (str, int, float, bool, None) will be skipped instead of raising a TypeError.

    json.dumps(obj, skipkeys=True)
    

    This solution is much cleaner and allows the standard library handle erroneous keys for you.

    WARNING: You must fully understand the implications of using such a drastic method as this will result in data loss for non-compliant data types as JSON keys.

    0 讨论(0)
  • 2020-12-09 11:04

    I know this is an old question and it already has an accepted answer, but alas the accepted answer is just totally wrong.

    The real issue here is that the code that generates the dict uses the builtin id function as key instead of the literal string "id". So the simple, obvious and only correct solution is to fix this bug at the source : check the code that generates the dict, and replace id with "id".

    0 讨论(0)
提交回复
热议问题