web-dev-qa-db-ja.com

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

この結果を取得したい:

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

しかし、このように宣言すると、これらのプロパティが正しくなくなります(期待される値による)。

foo_database.server.ip -> will be None
foo_database.user.name -> will be None

新しい「サーバー」オブジェクトには「ポート」プロパティのみがあり、古い「サーバー」オブジェクト全体をオーバーライドするためです。

達成したい種類の継承を取得するにはどうすればよいですか?

46
ceremcem

残念ながら、YAMLの「継承」は「ハッシュのマージ」の形式に似ているため、達成したい種類の「継承」を取得できません。

*defaultエイリアスを使用する時点で構成を展開すると、次のようになります。

foo_database:
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

後で同じキーでハッシュを使用する場合、それらは以前に宣言されたハッシュを完全に上書きします

foo_database:
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
   name: root
   password: root  
  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root

したがって、あなたの場合、設定はexactlyと同じではないので、アンカーとエイリアスを使用して設定を乾燥させることはおそらくそうではないようです正しいアプローチ。

この問題に関する以下の参考文献:

編集

本当にしたい場合は、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
33
Paul Fioravanti

これはどう?複数のアンカーを使用します。

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

それはほんの少し余分な作業であり、あなたが提案したようにあなたが望むものがYAMLに組み込まれている場合よりも読むのが少し難しいです(私はそれもそのように働くと思いました)。しかし、全体的には悪くありません。

10
Tyler Collier