[arrays] 목록 또는지도의 일부를 공유하기위한 YAML 구문이 있습니까?

그래서 나는 다음과 같이 할 수 있다는 것을 안다.

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

anotherlist: *sites

그리고이 sitelistanotherlist모두 포함 www.foo.com하고 www.bar.com. 그러나, 내가 정말 원하는 것은입니다 anotherlist 포함 www.baz.com반복하지 않고, www.foo.com하고 www.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을 사후 처리하는 아이디어에 대한 질문을 열어 보겠습니다.



답변

병합 키 유형 은 아마도 원하는 것입니다. <<병합을 나타 내기 위해 특수 매핑 키를 사용하여 매핑에 대한 별칭 (또는 이러한 별칭의 시퀀스)을 이니셜 라이저로 사용하여 단일 매핑으로 병합 할 수 있습니다. 또한 명시 적으로 값을 재정의하거나 병합 목록에없는 값을 더 추가 할 수 있습니다.

첫 번째 예로 시퀀스가 ​​아닌 매핑과 함께 작동한다는 점에 유의하는 것이 중요합니다. 이것은 당신이 그것에 대해 생각할 때 의미가 있으며, 당신의 예는 아마도 어쨌든 순차적 일 필요가없는 것처럼 보입니다. 시퀀스 값을 매핑 키로 변경하는 것만으로도 다음 (예상되지 않은) 예제와 같이 트릭을 수행 할 수 있습니다.

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

주목할 몇 가지. 첫째, <<키이므로 노드 당 한 번만 지정할 수 있습니다. 둘째, 시퀀스를 값으로 사용할 때 순서가 중요합니다. 관련 값이 없기 때문에 여기의 예제에서는 중요하지 않지만 알아 두어야 할 가치가 있습니다.


답변

이전 답변에서 지적했듯이 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으로 구현하고 여기에 게시 했습니다 .

즐겨!


답변

(내가 사용하는 솔루션이 나중에 이것을 검색하는 모든 사람에게 유용한 경우 내 질문에 대답)

이 작업을 수행하는 순수한 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:한다는 것을 보여주기 위해 외부지도를 계속 제공합니다. 즉 , 다른 최상위 이름이 없으면 최상위 이름으로 나타날 수 없습니다.)MERGEMERGE


답변

여기 두 가지 답변에서 무엇인가를 명확히하기 위해 이것은 목록의 YAML에서 직접 지원되지 않습니다 (그러나 사전에는 지원됩니다. kittemon의 답변 참조).


답변

Kittemon의 답변을 피기 백하려면 대체 구문을 사용하여 null 값으로 매핑을 만들 수 있습니다.

foo:
    << : myanchor
    bar:
    baz:

제안 된 구문 대신

foo:
    << : myanchor
    ? bar
    ? baz

Kittemon의 제안과 마찬가지로 매핑 내에서 앵커에 대한 참조를 사용하고 시퀀스 문제를 피할 수 있습니다. Symfony Yaml 구성 요소 v2.4.4가 ? bar구문을 다시 구성하지 않는다는 사실을 발견 한 후이 작업을 수행해야 합니다.


답변