Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YAML] Blank Array without Hash #9870

Closed
patrickheeney opened this issue Dec 27, 2013 · 13 comments
Closed

[YAML] Blank Array without Hash #9870

patrickheeney opened this issue Dec 27, 2013 · 13 comments
Labels

Comments

@patrickheeney
Copy link

Right now YAML component dumps an empty array like this: $dump = array('test' => array()); as test: { }. In some applications that use the YAML it needs to be test: [ ] a list instead of a hash.

In the symfony codebase on this line (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Yaml/Inline.php#L160) I found:

        $keys = array_keys($value);
        if ((1 == count($keys) && '0' == $keys[0])
            || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2)
        ) {

It looks to me if I pass $dump = array('test' => array('0' => '')) It should work? However this code outputs: test: - ''. Its successfully using the list format but its passing the blank value. I think another conditional is missing to be able to create: test: [ ]. I checked the unit tests and I can't find anywhere that explains what (1 == count($keys) && '0' == $keys[0]) was intended for other than this purpose.

EDIT: It doesn't look to be hitting that section of code at all since my indent level is really high. However I am still tring to figure out how to get it to output a [ ] instead of hash { } since it is invalid yaml for what I am using it for and a blank array defaults to the hash.

@jakzal
Copy link
Contributor

jakzal commented Jan 7, 2014

I'm afraid there's no good solution for your problem.

How can you tell that an empty array is suppose to be treated as a hash or an array? Furthermore, whatever we do we have to be consistent - so either dump an empty array as [] or {} - this means that one way or another you'll run into this problem.

@patrickheeney
Copy link
Author

I disagree on the consistency part since this a new feature request and not a change. I realize there is not a perfect solution for this so I am hoping we can come up with a way to make it work. I think the default empty array should be a hash {} as it is now. What I am looking for is setting or perhaps passing a certain type of array to force it to be an empty list [].

So I think if you want an empty hash then pass an empty array or if you want an empty list pass something in. Here are some ideas:

$dump = array('test' => array());
test: { }

$dump = array('test' => array('0' => ''));
test: [ ]

$dump = array('test' => array(null));
test: [ ]

$dump = array('test' => array(':empty:'));
test: [ ]

Adding detection for one of these types to output it a different way should be possible right? It would simply detect if count($keys) == 1 and $keys[0] == null or ':empty:' or empty($keys[0]). I agree that the default should not be changed and seeing as how [] is a new feature it should be backwards compatible?

@jakzal
Copy link
Contributor

jakzal commented Jan 7, 2014

What if you actually wanted the following:

$dump = array('test' => array('0' => ''));

to be dumped to:

test:
    - ''

The same question applies to the remaining proposals.

@patrickheeney
Copy link
Author

If you wanted that its the same thing as $dump = array('test' => array());. The empty array with a high nest level will produce (the following hashed list):

test:
   - ''

So I would just suggest to anyone using array('0' => '') to use array() if they want an empty hash list that does the same thing.

On the other examples I mentioned it is possible with :empty: that they would want to pass that as a string. However with null they would either want null as a string array('null') or not at all (since null gets forced to the string version anyway). The null (not string) version could be used to create an empty list.

The other suggestion from either of these is to pass an option to dump that can be used to tell it to use [] or {} but I don't know that this would completely solve my issue since its a global change. As it stands now, not offering a way to have an empty list causes my YAML to be invalid because my applications can't parse YAML hashes when its expecting a list. Both are valid YAML with completely different purposes so my hope is that both can be supported in some fashion.

Another potential idea:

$dump = array('test' => array(array()));

That would currently output YAML I believe like this:

test:
  - ''
    - ''

I don't know if that it is valid YAML anyway so it could be leveraged to create test: [ ].

@categulario
Copy link

I had the same problem.

maybe using standard objects for empty objects instead of arrays, like:

$dump = ['array' => [], 'object'=>(object)[]];

and the output

array: []
object: {}

@patrickheeney
Copy link
Author

@developingo good idea. That would be perfect.

@fabpot
Copy link
Member

fabpot commented Dec 24, 2014

implemented as of #10552

@fabpot fabpot closed this as completed Dec 24, 2014
@rkyoku
Copy link

rkyoku commented Jun 29, 2015

Sorry for the n00b question, but it seems to me that referenced issue (#10552) only updates the parse() method, and not the dump() method as specified in this ticket (#9870).

I indeed also encounter this issue: dump() should check if empty array is actually an empty object, and dump accordingly. It is important for some requirements (like, for example, Swagger)

Could you please reopen this issue?

@xabbuh
Copy link
Member

xabbuh commented Jun 30, 2015

I indeed also encounter this issue: dump() should check if empty array is actually an empty object, and dump accordingly.

How would you determine if an array should actually be an empty object?

@rkyoku
Copy link

rkyoku commented Jun 30, 2015

Just like it was proposed earlier. Use an empty stdClass instance. I
believe it is intuitive, actually. Array is array, stdClass is object.
Associative array is object, indexed array is array. Don't you agree ?

Le mar. 30 juin 2015 09:06, Christian Flothmann notifications@github.com
a écrit :

I indeed also encounter this issue: dump() should check if empty array is
actually an empty object, and dump accordingly.

How would you determine if an array should actually be an empty object?


Reply to this email directly or view it on GitHub
#9870 (comment).

@xabbuh
Copy link
Member

xabbuh commented Jun 30, 2015

The issue is that the dumper only handles PHP objects when you enable object support. If the support is not enabled, the dumper will always return null. Though if object support is enabled it will simply serialize the object and prefix it with !!php/object:. Changing this behaviour only for stdClass instances would be possible, but could be considered a BC break.

ping @symfony/deciders What do you think?

@rkyoku
Copy link

rkyoku commented Jun 30, 2015

What about adding a new parameter (false by default for BC) just like it
was added to the parse() method?

Le mar. 30 juin 2015 13:21, Christian Flothmann notifications@github.com
a écrit :

The issue is that the dumper only handles PHP objects when you enable
object support. If the support is not enabled, the dumper will always
return null. Though if object support is enabled it will simply serialize
the object and prefix it with !!php/object:. Changing this behaviour only
for stdClass instances would be possible, but could be considered a BC
break.

ping @symfony/deciders https://github.com/orgs/symfony/teams/deciders
What do you think?


Reply to this email directly or view it on GitHub
#9870 (comment).

@xabbuh
Copy link
Member

xabbuh commented Feb 8, 2016

see #17728

fabpot added a commit that referenced this issue Feb 28, 2016
This PR was merged into the 3.1-dev branch.

Discussion
----------

[Yaml] add option to dump objects as maps

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9870, #12860, #15781, #15937, #16266
| License       | MIT
| Doc PR        | TODO

Commits
-------

3941d2e [Yaml] add option to dump objects as maps
fabpot added a commit that referenced this issue Feb 19, 2017
…0657)

This PR was squashed before being merged into the 3.3-dev branch (closes #21471).

Discussion
----------

[Yaml] Allow dumping empty array as YAML sequence

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9870, #15937, #16266
| License       | MIT
| Doc PR        |

PHP arrays are dumped as either YAML sequences or mappings, depending on whether the array has continuos integer keys or not.

An empty array is always dumped as a YAML mapping. Sometimes you want it dumped as a YAML sequence instead.

Commits
-------

87ffaf2 Bump version number
af7067c Dump empty object as mapping
a6d94c1 [Yaml] Allow dumping empty array as YAML sequence
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants