【问题标题】:Symfony YAML format conversionSymfony YAML 格式转换
【发布时间】:2016-08-08 06:53:27
【问题描述】:

我有一些看起来像这样的服务定义:

MyService:
    class: Some\Class\Here
    factory:
        - SomeFactoryHere
        - method
    calls:
        - [add, ["@=service('AnotherService1').create(service('AnotherService2'), service('AnotherService3'), service('AnotherService3'))"]]

恕我直言,如果转换成这样的内容会更易读:

MyService:
    class: Some\Class\Here
    factory:
        - SomeFactoryHere
        - method
    calls:
        -
          add,
          "@=service('AnotherService1').create(
              service('AnotherService2'),
              service('AnotherService3'),
              service('AnotherService3')
          )"

但是,这不是有效的 YAML(Symfony 解析器失败),我的问题是如何将这个配置转换为上面的内容?

UPD#1

看看Symfony YAML format conversion: "calls" with string params - 重要的细微差别在那里。

【问题讨论】:

    标签: php symfony format yaml config


    【解决方案1】:

    分解字符串的最佳方法

    "@=service('AnotherService1').create(service('AnotherService2'), service('AnotherService3'), service('AnotherService3'))"
    

    是通过使用剥离的folded block scalar。这样做的限制是您不能使用反斜杠转义任何特殊字符,但这些不在您的示例中(您需要在标量周围使用 "" 的原因是因为它以 @ 开头,这是一个保留字符)。

    然后您还必须正确地重新表示您拥有的结构,正如@flyx 已经指出的那样:calls 的值是一个序列,其第一个元素是标量 add 和序列的列表由前面提到的长标量组成,为了便于阅读,您要对其进行分解:

    import yaml
    
    yaml_str = """\
    MyService:
        class: Some\Class\Here
        factory:
            - SomeFactoryHere
            - method
        calls:
            - - add
              - - >-
                  @=service('AnotherService1').create(
                  service('AnotherService2'),
                  service('AnotherService3'),
                  service('AnotherService3'))
    """
    
    data = yaml.safe_load(yaml_str)
    print(data)
    

    给予:

    "@=service('AnotherService1').create( service('AnotherService2'), service('AnotherService3'), service('AnotherService3'))"
    

    请注意,这会在 .create(service( 之间留出一个额外的空格。

    Symphony 使用的 YAML 解析器似乎无法解析上述内容(尽管它是正确的)。您也可以尝试:

    MyService:
        class: Some\Class\Here
        factory:
            - SomeFactoryHere
            - method
        calls:
            - 
              - add
              - 
                - >-
                  @=service('AnotherService1').create(
                  service('AnotherService2'),
                  service('AnotherService3'),
                  service('AnotherService3'))
    

    【讨论】:

    • 我的回答没有在结果字符串中添加任何空格。你是怎么想到的?
    • @flyx 加载它然后转储它,就像我一样。
    • 如果您选择的 YAML 实现在我的答案中为标量添加了空格,则它不是正确的 YAML 实现。规范说All leading and trailing white space characters are excluded from the content..
    • 我看到你使用 PyYAML。 Python 支持长字符串中的反斜杠转义,因此请确保转义 YAML 中的反斜杠以获得正确的输出。
    • symphony 使用的解析器不兼容。您可以在yaml-online-parser.appspot.comyamllint.com 进行测试。我将使用带有此缺陷的 symphony 可能能够理解的内容来更新示例。
    【解决方案2】:

    你写的是有效的 YAML。如果 Symfony 解析器失败,它就有一个错误。但无论如何,第二个 YAML 与第一个 YAML 代表的结构不同。

    在第一个 YAML 中,calls 是一个序列。 calls 的第一个序列项也是一个序列,它包含标量 add 和另一个序列。在第二个 YAML 中,calls 也是一个序列,但它包含的项目是一个标量,其中包含从 add,)" 的所有内容。逗号是这里的内容,因为您没有启动流序列(使用[)。这里是块式 YAML,相当于第一个 YAML:

    MyService:
        class: Some\Class\Here
        factory:
            - SomeFactoryHere
            - method
        calls:
            - - add
              - - "@=service('AnotherService1').create(\
                     service('AnotherService2'),
                     service('AnotherService3'),
                     service('AnotherService3')\
                  )"
    

    字符串行尾的反斜杠不会插入空格。默认情况下,YAML 会为遇到的双引号字符串中的每个换行符插入一个空格字符。此 YAML 标量产生的字符串与您的第一个 YAML 包含的字符串完全相同。

    - - 是简洁风格,它同时启动两个嵌套的序列项。所以现在,calls 又是一个以序列作为第一项的序列。该嵌套序列包含一个标量 add 作为第一项,另一个序列作为第二项。该序列包含双引号标量。

    【讨论】:

    • 如果您在逗号和反斜杠之间插入一个空格,那么引用的标量将得到两个空格,就像在示例中一样(在中间两行)
    • 啊,是的,我忽略了这些。更新了答案,在需要空格的地方不包含反斜杠 - 这比在反斜杠前添加空格更简单。
    • 在 Symfony 中,这失败了: Unable to parse at line 619 (near " - - "@=service('AnotherService1').create(\").
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多