Python JSON encoder to support datetime?

后端 未结 9 1885
长发绾君心
长发绾君心 2020-12-03 10:24

is there any elegant way to make Python JSON encoder support datetime? some 3rd party module or easy hack?

I am using tornado\'s database wrapper to fetch some rows

相关标签:
9条回答
  • 2020-12-03 10:58

    Convert the datetime type into a unix timestamp, then encode the contents into a json.

    e.g. : http://codepad.org/k3qF09Kr

    0 讨论(0)
  • 2020-12-03 11:03

    Create a custom decoder/encoder:

    class CustomJSONEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj, datetime.datetime):
                return http_date(obj)
            if isinstance(obj, uuid.UUID):
                return str(obj)
            return json.JSONEncoder.default(self, obj)
    
    class CustomJSONDecoder(json.JSONDecoder):
        def __init__(self, *args, **kwargs):
            json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
    
        def object_hook(self, source):
            for k, v in source.items():
                if isinstance(v, str):
                    try:
                        source[k] = datetime.datetime.strptime(str(v), '%a, %d %b %Y %H:%M:%S %Z')
                    except:
                        pass
            return source
    
    0 讨论(0)
  • 2020-12-03 11:03

    Just create a custom encoder

    (the small but important addition to Cole's answer is the handling of pd.NaT (or null/empty timestamp values), since without the addition you will get very weird timestamp conversions for NaT/missing timestamp data)

    class CustomEncoder(json.JSONEncoder):
        def default(self, obj):
            if pd.isnull(obj):
                return None
            elif isinstance(obj, datetime):
                return obj.isoformat()
            elif isinstance(obj, date):
                return obj.isoformat()
            elif isinstance(obj, timedelta):
                return (datetime.min + obj).time().isoformat()
            else:
                return super(CustomEncoder, self).default(obj)
    

    Then use it to encode a dataframe:

    df_as_dict = df.to_dict(outtype = 'records')  # transform to dict
    
    df_as_json = CustomEncoder().encode(df_as_dict) #transform to json
    

    Since the encoder standardized the data, the regular decoder will act fine in transforming it back to a dataframe:

    result_as_dict = json.JSONDecoder().decode(df_as_json) # decode back to dict
    
    result_df = pd.DataFrame(result)  # transform dict back to dataframe
    

    Of course this will also work if you put the dataframe into a larger dict before encoding, e.g

    input_dict = {'key_1':val_1,'key_2':val_2,...,'df_as_dict':df_as_dict}
    input_json = CustomEncoder().encode(input_dict)
    input_json_back_as_dict = json.JSONDecoder().decode(input_json)
    input_df_back_as_dict = input_json_back_as_dict['df_as_dict']
    input_df_back_as_df = pd.DataFrame(input_df_back_as_dict)
    
    0 讨论(0)
提交回复
热议问题