113

だから、私はこのようなことをすることができることを知っています:

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist: *sites

そして、持っているsitelistanotherlist両方が含まれwww.foo.comていwww.bar.comます。しかし、私が本当に望んでいるのは、とを繰り返す必要なしに、anotherlist含むことです。www.baz.comwww.foo.comwww.baz.com

これを行うと、YAMLパーサーで構文エラーが発生します。

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist: *sites
  - www.baz.com

アンカーとエイリアスを使用するだけでは、次のような別のレベルの下部構造を追加せずに、私が望むことを実行することはできないようです。

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist:
  - *sites
  - www.baz.com

つまり、このYAMLファイルの利用者はそれを認識している必要があります。

このようなことを行う純粋なYAMLの方法はありますか?または、変数の置換や特定の種類の下部構造の自動リフトの実装など、YAML後の処理を使用する必要がありますか?私はすでにその種の後処理を行って、他のいくつかのユースケースを処理しているので、私はそれを完全に嫌うわけではありません。ただし、私のYAMLファイルは、マシンで生成されるのではなく、人間によって書き込まれるため、標準のYAML構文に加えて、ユーザーが記憶する必要のあるルールの数を最小限に抑えたいと思います。

また、マップでも同様のことができるようにしたいと思います。

namedsites: &sites
  Foo: www.foo.com
  Bar: www.bar.com

moresites: *sites
  Baz: www.baz.com

YAML仕様を検索しましたが、何も見つかりませんでした。そのため、答えは「いいえ、これはできません」と思われます。しかし、誰かが素晴らしいアイデアを持っているなら。


編集:答えがなかったので、私はYAML仕様にないものを誰も発見しておらず、これはYAMLレイヤーでは実行できないと推測しています。ですから、将来誰かがこの質問を見つけた場合に備えて、これを支援するためにYAMLを後処理するためのアイデアに質問を開いています。

4

5 に答える 5

61

マージ キーのタイプは、おそらく必要なものです。特別な<<マッピング キーを使用してマージを示し、マッピングへのエイリアス (またはそのようなエイリアスのシーケンス) をイニシャライザとして使用して単一のマッピングにマージできるようにします。さらに、値を明示的にオーバーライドしたり、マージ リストに存在しなかった値を追加したりすることもできます。

最初の例のようにシーケンスではなく、マッピングで機能することに注意することが重要です。これは、考えてみると理にかなっています。あなたの例は、おそらくシーケンシャルである必要はないように見えます。次の(テストされていない)例のように、シーケンス値をマッピングキーに変更するだけでうまくいくはずです。

sitelist: &sites
  ? www.foo.com  # "www.foo.com" is the key, the value is null
  ? www.bar.com

anotherlist:
  << : *sites    # merge *sites into this mapping
  ? www.baz.com  # add extra stuff

注意すべき点がいくつかあります。まず、<<はキーであるため、ノードごとに 1 回しか指定できません。次に、シーケンスを値として使用する場合、順序が重要になります。この例では値が関連付けられていないため、これは問題ではありませんが、注意が必要です。

于 2012-03-01T23:34:37.400 に答える
8

(私が使用しているソリューションが将来これを検索する人に役立つ場合に備えて、私自身の質問に答えてください)

これを行うための純粋なYAMLの方法がないため、YAMLパーサーと実際に構成ファイルを使用するコードの間にある「構文変換」としてこれを実装します。したがって、私のコアアプリケーションは、人間に優しい冗長性回避策についてまったく心配する必要がなく、結果として得られる構造に直接作用することができます。

使用する構造は次のようになります。

foo:
  MERGE:
    - - a
      - b
      - c
    - - 1
      - 2
      - 3

これは、次のものと同等に変換されます。

foo:
  - a
  - b
  - c
  - 1
  - 2
  - 3

または、マップを使用する場合:

foo:
  MERGE:
    - fork: a
      spoon: b
      knife: c
    - cup: 1
      mug: 2
      glass: 3

次のように変換されます:

foo:
  fork: a
  spoon: b
  knife: c
  cup: 1
  mug: 2
  glass: 3

より正式には、YAMLパーサーを呼び出して構成ファイルからネイティブオブジェクトを取得した後、オブジェクトをアプリケーションの残りの部分に渡す前に、アプリケーションはオブジェクトグラフを調べて、単一のキーを含むマッピングを探しますMERGE。に関連付けられている値MERGEは、リストのリストまたはマップのリストのいずれかである必要があります。その他の下部構造はエラーです。

リストのリストの場合、含むマップ全体が、MERGE表示された順序で連結された子リストに置き換えられます。

マップのリストの場合、を含むマップ全体MERGEが、子マップのすべてのキーと値のペアを含む単一のマップに置き換えられます。MERGEキーが重複している場合は、リストの最後にある子マップの値が使用されます。

上記の例は、必要な構造を直接記述できた可能性があるため、それほど有用ではありません。次のように表示される可能性が高くなります。

foo:
  MERGE:
    - *salt
    - *pepper

ノード内のすべてを含み、他の場所で使用されているリストまたはマップを作成できるようにしsaltますpepper

(私はそのfoo:外側のマップを与え続けて、それがそのマッピングの唯一のキーでMERGEなければならないことを示します。つまり、他のトップレベルの名前がない限り、トップレベルの名前として表示することはできません)MERGE

于 2012-02-17T03:20:50.913 に答える