YAML中更复杂的继承?

cer*_*cem 47 inheritance yaml

YAML有继承权.我见过的最明显的例子是:http://blog.101ideas.cz/posts/dry-your-yaml-files.html

我需要更复杂的东西:我需要覆盖对象的对象的属性.这是一个例子:

database: &default
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

# database foo differs from default by only its port and user password
foo_database:
  <<: *default
  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root
Run Code Online (Sandbox Code Playgroud)

我想得到这个结果:

foo_database.server.ip -> 192.168.1.5
foo_database.server.port -> 2001
foo_database.db_name -> foo
foo_database.user.name -> root
foo_database.user.password -> foo_root
Run Code Online (Sandbox Code Playgroud)

但是,如果您这样声明,您将获得这些属性不正确(根据预期值):

foo_database.server.ip -> will be None
foo_database.user.name -> will be None
Run Code Online (Sandbox Code Playgroud)

因为新的"服务器"对象只有"port"属性,它会覆盖整个旧的"服务器"对象.

我如何获得我想要实现的继承?

Pau*_*nti 34

不幸的是,你不能得到你想要实现的那种"继承",因为YAML的"继承"更像是一种"融合哈希".

在使用*default别名时扩展配置,您有:

foo_database:
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root
Run Code Online (Sandbox Code Playgroud)

如果你之后使用具有相同键的哈希,它们将完全覆盖前面声明的哈希值,留下你(原谅格式化):

foo_database:
Run Code Online (Sandbox Code Playgroud)

  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
   name: root
   password: root  
Run Code Online (Sandbox Code Playgroud)

  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root
Run Code Online (Sandbox Code Playgroud)

因此,在您的情况下,似乎由于配置不完全相同,使用锚点和别名来干扰您的配置可能不是正确的方法.

关于这个问题的更多参考如下:

编辑

如果你真的想,我认为你可以重新配置你的YAML如下所示,以获得你想要的,但在你的情况下,我会说额外的混淆是不值得的:

server_defaults: &server_defaults
  ip: 192.168.1.5
  port: 2000

user_defaults: &user_defaults
  name: root
  password: root

database: &default
  server:
    <<: *server_defaults
  db_name: test
  user: 
    <<: *user_defaults

foo_database:
  <<: *default
  server:
    <<: *server_defaults
    port: 2001
  db_name: foo
  user:
    <<: *user_defaults
    password: foo_root
Run Code Online (Sandbox Code Playgroud)


Tyl*_*ier 11

这个怎么样?使用多个锚点.

database: &default
  server: &server
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: &user
    name: root
    password: root

foo_database:
  <<: *default
  server:
    << : *server
    port: 2001
  db_name: foo
  user:
    << : *user
    password: foo_root
Run Code Online (Sandbox Code Playgroud)

这只是一点点额外的工作,并且比你想要的内容更难以阅读(正如你所建议的那样)(我认为它也可以这样工作).但总的来说还不错.