I want to parse (json.loads) a json string that contains datetime values sent from a http client.
我想解析(json.loads)一个包含从http客户端发送的日期时间值的json字符串。
I know that I can write a custom json encoder by extending the default encoder and overriding the default method
我知道我可以通过扩展默认编码器并覆盖默认方法来编写自定义json编码器
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.datetime,)):
return obj.isoformat()
elif isinstance(obj, (decimal.Decimal,)):
return str(obj)
else:
return json.JSONEncoder.default(self, obj)
My questions are -
我的问题是 -
- How do I customize the default json decoder? Do I need to override the decode method? Can I in some way, override/add a callback function for every field/value in the json string? (I have seen the code in json.decoder.JSONDecoder and json.scanner but am not sure what to do)
- Is there an easy way to identify a specific value as a datetime string? The date values are strings in ISO format.
如何自定义默认的json解码器?我需要覆盖解码方法吗?我能以某种方式覆盖/添加json字符串中每个字段/值的回调函数吗? (我在json.decoder.JSONDecoder和json.scanner中看过代码,但不知道该怎么做)
有没有一种简单的方法可以将特定值标识为日期时间字符串?日期值是ISO格式的字符串。
Thanks,
2 个解决方案
#1
4
There are likely other solutions, but json.load
& json.loads
both take an object_hook
argument1 that is called with every parsed object, with its return value being used in place of the provided object in the end result.
可能还有其他解决方案,但是json.load和json.loads都接受一个object_hook参数1,该参数使用每个已解析的对象调用,其返回值用于代替最终结果中提供的对象。
Combining this with a little tag in the object, something like this is possible;
将它与对象中的一个小标签相结合,这样的事情是可能的;
import json
import datetime
import dateutil.parser
import decimal
CONVERTERS = {
'datetime': dateutil.parser.parse,
'decimal': decimal.Decimal,
}
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.datetime,)):
return {"val": obj.isoformat(), "_spec_type": "datetime"}
elif isinstance(obj, (decimal.Decimal,)):
return {"val": str(obj), "_spec_type": "decimal"}
else:
return super().default(obj)
def object_hook(obj):
_spec_type = obj.get('_spec_type')
if not _spec_type:
return obj
if _spec_type in CONVERTERS:
return CONVERTERS[_spec_type](obj['val'])
else:
raise Exception('Unknown {}'.format(_spec_type))
def main():
data = {
"hello": "world",
"thing": datetime.datetime.now(),
"other": decimal.Decimal(0)
}
thing = json.dumps(data, cls=MyJSONEncoder)
print(json.loads(thing, object_hook=object_hook))
if __name__ == '__main__':
main()
#2
0
As for 2nd question, you should propably just use
至于第二个问题,你应该可以使用
import dateutil.parser dateutil.parser.parse('Your string')
import dateutil.parser dateutil.parser.parse('Your string')
method, it will try to parse your date string, and if it wouldn't be able to recognize it, it will throw Value Error. You can also use regular expressions to find fields that at least look like a dates (depending on the format you use, of course)
方法,它将尝试解析您的日期字符串,如果它无法识别它,它将抛出值错误。您还可以使用正则表达式查找至少看起来像日期的字段(当然,取决于您使用的格式)
#1
4
There are likely other solutions, but json.load
& json.loads
both take an object_hook
argument1 that is called with every parsed object, with its return value being used in place of the provided object in the end result.
可能还有其他解决方案,但是json.load和json.loads都接受一个object_hook参数1,该参数使用每个已解析的对象调用,其返回值用于代替最终结果中提供的对象。
Combining this with a little tag in the object, something like this is possible;
将它与对象中的一个小标签相结合,这样的事情是可能的;
import json
import datetime
import dateutil.parser
import decimal
CONVERTERS = {
'datetime': dateutil.parser.parse,
'decimal': decimal.Decimal,
}
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.datetime,)):
return {"val": obj.isoformat(), "_spec_type": "datetime"}
elif isinstance(obj, (decimal.Decimal,)):
return {"val": str(obj), "_spec_type": "decimal"}
else:
return super().default(obj)
def object_hook(obj):
_spec_type = obj.get('_spec_type')
if not _spec_type:
return obj
if _spec_type in CONVERTERS:
return CONVERTERS[_spec_type](obj['val'])
else:
raise Exception('Unknown {}'.format(_spec_type))
def main():
data = {
"hello": "world",
"thing": datetime.datetime.now(),
"other": decimal.Decimal(0)
}
thing = json.dumps(data, cls=MyJSONEncoder)
print(json.loads(thing, object_hook=object_hook))
if __name__ == '__main__':
main()
#2
0
As for 2nd question, you should propably just use
至于第二个问题,你应该可以使用
import dateutil.parser dateutil.parser.parse('Your string')
import dateutil.parser dateutil.parser.parse('Your string')
method, it will try to parse your date string, and if it wouldn't be able to recognize it, it will throw Value Error. You can also use regular expressions to find fields that at least look like a dates (depending on the format you use, of course)
方法,它将尝试解析您的日期字符串,如果它无法识别它,它将抛出值错误。您还可以使用正则表达式查找至少看起来像日期的字段(当然,取决于您使用的格式)