2012-02-13 14 views
50

所以,我知道我可以做這樣的事情:是否有用於共享列表或地圖的部分的YAML語法?

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

anotherlist: *sites 

而且具有sitelistanotherlist都包含www.foo.comwww.bar.com。但是,我真正想要的是anotherlist包含www.baz.com,而不必重複www.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 spec搜索,也找不到任何東西,所以我懷疑,答案是隻是「不,你不能這樣做」。但是,如果任何人有任何想法會很棒。


編輯:由於沒有出現過答案,我假定沒有人發現什麼,我在YAML規範,這不能在YAML層來完成沒有。因此,我打開這個問題想到後處理YAML來幫助解決這個問題,以防將來有人發現這個問題。

+0

**注意:**此問題也可以通過在YAML中標準使用錨和別名來解決。 **另請參閱:** [如何合併YAML數組?](http://stackoverflow.com/a/30770740/42223) – dreftymac 2017-04-28 10:22:57

回答

4

(回答我的問題的情況下,我使用的解決方案是任何人誰在未來的這個搜索有用)

由於沒有純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 

允許您創建中的節點saltpepper列表或一切包含地圖被用於其他地方。

(我一直在給那foo:外映射表明MERGE必須在其映射只有關鍵,這意味着除非沒有其他頂級名MERGE不能作爲一個頂級名)

41

The merge key type可能是你想要的。它使用特殊的映射鍵來指示合併,允許將映射的別名(或這樣的別名序列)用作初始化器以合併成單個映射。此外,您仍然可以顯式覆蓋值,或者添加更多不存在於合併列表中的值。

重要的是要注意它適用於映射,而不是序列作爲第一個示例。這是有道理的,當你考慮它時,你的例子看起來可能不需要順序。簡單地改變你的序列值映射鍵應該做的伎倆,如下面的(未經測試)例如:

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 

有些事情需要注意。首先,由於<<是一個關鍵,因此每個節點只能指定一次。其次,當使用序列作爲值時,順序非常重要。這裏沒有關係,因爲沒有關聯的值,但值得注意。

+0

啊,謝謝!這很有幫助。儘管如此,這對於序列來說並不適用。你說得對,這個例子並不重要,我所擁有的在概念上是一個集合,但是它更接近於一個序列而不是一個映射。我從中得到的結構很重要(這就是爲什麼我不想僅僅添加另一個嵌套層來合併我的結構),所以有一個映射,我需要忽略(全爲null)值真的沒用。 – Ben 2012-03-02 00:14:57

+2

目前官方的YAML規範中沒有看到任何內容:http://www.yaml.org/spec/1.2/spec.html。該頁面不包含單詞「合併」,也不包含文本「<<」,也不包含「密鑰類型」。儘管<<語法在Python yaml包中工作。你知道我在哪裏可以找到更多關於這些額外功能的信息嗎? – Ben 2012-03-02 00:18:07

+1

這不是直接在規範中,它在標籤庫中描述。 [其他模式](http://www.yaml.org/spec/1.2/spec.html#id2805770)有一個一般描述和鏈接。除了合併密鑰外,還有集合和有序集合;然而,YAML認爲集合是一種映射(例如,上面的例子可以作爲一個集合來實現)。您的語言是否允許您將鍵與交換結果中的值交換?即使你必須自己實現,我認爲它會更清潔。你至少已經把所有的數據組合在一起了,你的YAML將是標準的。 – kittemon 2012-03-02 00:39:24

3

爲了澄清這裏的兩個答案,這不直接支持YAML中的列表(但它支持字典,請參閱kittemon的答案)。

+0

**注:**此問題也可以通過在YAML中標準使用錨和別名來解決。 **參見:** [如何合併YAML陣列?(http://stackoverflow.com/a/30770740/42223) – dreftymac 2017-04-28 10:21:03

4

能借助Kittemon的回答,請注意,您可以使用替代語法

foo: 
    << : myanchor 
    bar: 
    baz: 

,而不是建議的語法

foo: 
    << : myanchor 
    ? bar 
    ? baz 

像Kittemon的建議,這將允許創建一個空值映射您可以在映射中使用對錨點的引用並避免序列問題。在發現Symfony Yaml組件v2.4.4不記錄? bar語法後,我發現自己需要這樣做。

4

正如前面的答案指出的那樣,沒有內置的支持在YAML中擴展列表。我正在提供另一種自己實現的方法。試想一下:

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

setup1: 
    <<: *defaults 
    sites+: 
    - www.baz.com 

這將被加工成:

defaults: 
    sites: 
    - www.foo.com 
    - www.bar.com 

setup1: 
    sites: 
    - www.foo.com 
    - www.bar.com 
    - www.baz.com 

的想法是一個關鍵結局的內容與「+」合併沒有「+」對應的按鍵。我在Python中實現了這個功能,併發布了here

享受!

+0

**注:**此問題也可能與標準使用錨和別名來解決在YAML。 **另請參閱:** [如何合併YAML數組?](http://stackoverflow.com/a/30770740/42223) – dreftymac 2017-04-28 10:20:43

+0

Excellents .. !!謝謝,它幫助了我..! – 2017-12-28 09:11:44

相關問題