我一直在尝试实现一个“抽象”模式类,该类将自动将CamelCase(序列化)中的值转换为snake_case(反序列化)。
class CamelCaseSchema(marshmallow.Schema):
@marshmallow.pre_load
def camel_to_snake(self, data):
return {
utils.CaseConverter.camel_to_snake(key): value for key, value in data.items()
}
@marshmallow.post_dump
def snake_to_camel(self, data):
return {
utils.CaseConverter.snake_to_camel(key): value for key, value in data.items()
}
虽然使用类似的方法效果很好,但是并不能将load_from
和dump_to
应用于字段就可以实现。也就是说,当反序列化出现问题时,它无法提供正确的字段名称。例如,我得到:
{'something_id': [u'Not a valid integer.']}
而不是{'somethingId': [u'Not a valid integer.']}
。
虽然我可以对这些发出的错误进行后处理,但是这似乎是不必要的耦合,如果我想使模式的使用完全透明,我希望避免这种耦合。
有什么想法吗?我尝试解决涉及的元类,但是复杂性有点不堪重负,并且一切似乎都非常丑陋。
答案 0 :(得分:2)
您正在使用棉花糖2。棉花糖3现已推出,我建议您使用它。我的答案将适用于棉花糖3。
在棉花糖3中,load_from
/ dump_to
被单个属性data_key
取代。
实例化架构时,您需要在每个字段中更改data_key
。在字段实例化之后会发生这种情况,但我认为这并不重要。
您要在实例化架构时尽快执行该操作,以避免出现不一致问题。正确的时机应该在Schema._init_fields
属性的一致性检查之前的data_key
中间。但是复制这种方法将是可惜的。此外,由于骆驼/蛇格转换的性质,无论如何都可以在转换之前应用一致性检查。
而且由于_init_fields
是私有API,因此建议您在__init__
的末尾进行修改。
class CamelCaseSchema(Schema):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for field_name, field in self.fields.items():
fields.data_key = utils.CaseConverter.snake_to_camel(field_name)
我没有尝试过,但我认为应该可以。