我正在创建一个YAML文件来保存与XML项目相关的元数据,并且我只使用Python作为测试工具 - 它不是一个python项目。
所以,我想编写一些类来保存数据,我很惊讶地发现让PyYAML自动将文件读入这些类的标准方法是使用YAML标记(例如{{1}实例化Monster对象)。
我不想使用标签,因为我希望这些YAML文件尽可能便携 - 任何想要的人都可以使用他们选择的语言(像JSON一样可移植)。
在我看来,数据绑定信息不属于YAML文件,作为一般原则,但谷歌搜索一段时间后,我似乎无法找到其他人抱怨这一点。我确实发现很多人都在问如何使用无法识别的标签来解析YAML,如何忽略标签等等 - 所以我认为标签确实会给数据消费者造成问题。
我喜欢使用内省和注释Jackson的工作方式(用于在Java中解析JSON)。在Python中解析YAML有类似的东西吗?
以下是我正在讨论的YAML内容的一个示例:
!Monster
我想将其映射到Split类的对象列表,其中包含一系列属性,包括一个乐器列表和一个歌曲列表。
答案 0 :(得分:1)
手动方式是定义以下内容:
class Instrument(object):
def __getstate__(self):
return {
"path": self.path,
"url": self.url,
}
def __setstate__(self, state):
self.path = state["path"]
self.url = state["url"]
class Song(object):
def __getstate__(self):
return {
"name": self.name,
"genre": self.genre,
}
def __setstate__(self, state):
self.name = state["name"]
# Note that this can be non-present -> store None
self.genre = state.get("genre")
self.year = state.get("year")
class Split(object):
def __getstate__(self):
return {
"name": self.name,
"color": self.color,
"instruments": [i.__getstate__() for i in self.instruments],
"songs": [s.__getstate__() for s in self.songs],
}
def __setstate__(self, state):
self.name = state["name"]
self.color = state["color"]
self.instruments = list()
for i_state in state["instruments"]:
i = Instrument.__new__(Instrument)
i.__setstate__(i_state)
self.instruments.append(i)
self.songs = list()
for s_state in state["songs"]:
s = Song.__new__(Song)
s.__setstate__(s_state)
self.songs.append(s)
请注意,我使用__getstate__
和__setstate__
只是为了与pickle
以及一些典型应用程序保持友好关系,但您可以使用其他名称。
然后,假设您在名为data
的变量中包含YAML文档,您只需:
structured_data = yaml.load(data)
list_of_splits = list()
for s_state in structured_data:
s = Split.__new__(Split)
s.__setstate__(s_state)
list_of_splits.append(s)
structured_data
将包含变体内容的词典列表。但这一切都将是简单的类型。 __setstate__
递归过程可确保所有内容都符合预期 - 但您必须定义预期的内容,因为我们没有类型或任何其他类型的提示。
可以定义某种提示以自动化此行为。我想的是:
class Split(AutoMagicYAMLObject):
name = StringField()
color = StringField()
instruments = ListField(Instrument)
songs = ListField(Song)
...但这将是一个有趣的应用程序,充满了极端案例和精巧的设计决策:)我不知道任何现有的包做类似的事情,所以无法帮助更多。