serializer icon indicating copy to clipboard operation
serializer copied to clipboard

Inline array serialization without entry tag

Open BarryBadpak opened this issue 5 years ago • 8 comments

I have a question regarding the inline serialization of arrays, when providing a structure as shown below, is it possible to serialize an array inline without getting a wrapper element around it?

Code:

 * Class Interchange
 * @Serializer\XmlRoot("Interchange")
 */
class Interchange
{
    /**
     * @var Message[]
     * @Serializer\Inline
     */
    protected $messages;

    /**
     * @param Message|Message[] $messages
     */
    public function addMessage($messages)
    {
        if (!is_array($messages)) {
            $messages = [$messages];
        }

        $this->messages = $messages;
    }
}

class Message
{
    /**
     * @var Segment[]
     * @Serializer\Inline
     * @Serializer\XmlKeyValuePairs
     */
    protected $segments;

    /**
     * @param string $key
     * @param Segment $segment
     */
    public function addSegment(string $key, Segment $segment)
    {
        $this->segments[$key] = $segment;
    }
}

class Segment
{
    protected $test = 'value';
}

However it gets serialized to:

<?xml version="1.0" encoding="UTF-8"?>
<Interchange>
  <entry>
    <UNB>
      <test><![CDATA[value]]></test>
    </UNB>
    <UNH>
      <test><![CDATA[value]]></test>
    </UNH>
    <UNT>
      <test><![CDATA[value]]></test>
    </UNT>
    <UNZ>
      <test><![CDATA[value]]></test>
    </UNZ>
  </entry>
  <entry>
    <UNB>
      <test><![CDATA[value]]></test>
    </UNB>
    <UNH>
      <test><![CDATA[value]]></test>
    </UNH>
    <UNT>
      <test><![CDATA[value]]></test>
    </UNT>
    <UNZ>
      <test><![CDATA[value]]></test>
    </UNZ>
  </entry>
</Interchange>

Is there a way to serialize an array inline without getting the entry tag wrapped around it?

BarryBadpak avatar May 28 '19 16:05 BarryBadpak

Have you tried to use @XmlList ? (see http://jmsyst.com/libs/serializer/master/reference/annotations#xmllist there is the inline option...)

goetas avatar May 28 '19 18:05 goetas

Yea I've tried that one. I added it as followed:

/**
* @var Message[]
* @Serializer\XmlList(inline = true)
*/
protected $messages;

It then still wraps these within a <entry>...Serialized Message...</entry> element. I didn't find anything in the documentation about getting rid of this wrapper element.

I also tried specifying the entry = "" option but that leads to an invalid character exception as a node name can not be empty.

BarryBadpak avatar May 28 '19 18:05 BarryBadpak

Can you please post what is the expected xml?

goetas avatar May 28 '19 18:05 goetas

The expected xml for me would be as followed below. I added a comment to show the distinction between the first and second array element serialization.

<?xml version="1.0" encoding="UTF-8"?>
<Interchange>
    <UNB>
      <test><![CDATA[value]]></test>
    </UNB>
    <UNH>
      <test><![CDATA[value]]></test>
    </UNH>
    <UNT>
      <test><![CDATA[value]]></test>
    </UNT>
    <UNZ>
      <test><![CDATA[value]]></test>
    </UNZ>
    <!-- Second Message element gets serialized below) -->
    <UNB>
      <test><![CDATA[value]]></test>
    </UNB>
    <UNH>
      <test><![CDATA[value]]></test>
    </UNH>
    <UNT>
      <test><![CDATA[value]]></test>
    </UNT>
    <UNZ>
      <test><![CDATA[value]]></test>
    </UNZ>
</Interchange>

BarryBadpak avatar May 28 '19 18:05 BarryBadpak

Hmm, It looks the combination with the @Inline annotation and the @XmlKeyValuePairs annotation... Not sure it will work out of the box.

goetas avatar May 29 '19 07:05 goetas

Unfortunately it also results in a entry node wrapped around it, the documentation of @XmlKeyValuePairs also states Note: When a key is an invalid xml tag name (e.g. 1_foo) the tag name entry will be used instead of the key.

I think as of now there is no out of the box way of making this work with annotations, as there is no option for arrays to not have a node around its elements.

I'll play around with it a bit more and maybe see if I can add a extra parameter to the @XmlList annotation, as it does not care about array keys and it already has a inline parameter and a entry parameter to change the node name.

Looking at the code for the XML serialization it also shows that for arrays there is no way of getting rid of the entry node: https://github.com/schmittjoh/serializer/blame/master/src/XmlSerializationVisitor.php#L191

Thanks for your help though!

BarryBadpak avatar May 29 '19 07:05 BarryBadpak

I would also love to see such functionality. XmlList requires a value for entry which conflicts with custom setPropertyNamingStrategy.

xorock avatar Jan 26 '24 10:01 xorock

Hi! Feel free to make Pull Request with this functionality :) I can help with going through the process.

Best, scyzoryck

scyzoryck avatar Jan 29 '24 21:01 scyzoryck