The response of a REST resource has the root element set to always. Is there a way to change this. Its set in \Symfony\Component\Serializer\Encoder\XmlEncoder or JsonEncoder

I have created a custom rest resource.

Comments

abhishek-anand created an issue. See original summary.

abhishek-anand’s picture

Issue summary: View changes
wim leers’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: -serialization, -json_encode
Related issues: +#2800873: Add XML GET REST test coverage, work around XML encoder quirks
  1. Why do you want to change the "root element"?
  2. JSON-encoded responses do not have a root, so I'm not sure what you mean.
  3. So, assuming you're referring to XML, I'd like to warn you that XML support may be dropped, because it's completely broken: #2800873: Add XML GET REST test coverage, work around XML encoder quirks
  4. Why is this tagged with services? Are you using https://www.drupal.org/project/services perhaps?
abhishek-anand’s picture

Why do you want to change the "root element"?

This is a requirement for my custom rest resource.

JSON-encoded responses do not have a root, so I'm not sure what you mean.

I am using an XMLEndpoint.

Why is this tagged with services? Are you using https://www.drupal.org/project/services perhaps?

No, I am using core rest module. I tagged it incorrectly.

wim leers’s picture

Issue tags: -services
  1. Ok.
  2. Ok.
  3. You did not respond to this.
  4. Ok. Removing the tag.

Can you explain why you're using XML? Like I said, chances are we'll drop XML support. You're the very first user I encounter who actually is using the xml format.


Now that I have the necessary background info, I can look into this and formulate a proper answer. In the mean time, please answer the above question.

abhishek-anand’s picture

So, assuming you're referring to XML, I'd like to warn you that XML support may be dropped, because it's completely broken: #2800873: 'xml' format broken: Symfony's XmlEncoder maps a single-item array to a non-array

I am working with a client who is migrating from a different platform to drupal, maintaining their previous api endpoints. We have no choice but to generate XML endpoints, otherwise their frontend which is consuming those endpoints will break.

wim leers’s picture

Thanks, that's a very good reason!

wim leers’s picture

Title: Change the root element of a rest resource. » Change the root node name of a custom REST resource's XML encoding

Using a different root node for the xml format is equivalent with using a custom format. So, you must specify your own format. Let's assume it's called foo_xml, and the root node should be foo.

Then you'll want to do something like this, in a custom module:

use \Drupal\serialization\Encoder\XmlEncoder;

class FooXmlEncoder extends XmlEncoder {

  /**
   * {@inheritdoc}
   */
  static protected $format = ['foo_xml'];

  /**
   * {@inheritdoc}
   */
  public function getBaseEncoder() {
    $base_encoder = parent::getBaseEncoder();
    $base_encoder->setRootNodeName('foo');
    return $base_encoder;
  }
}

And this in its *.services.yml file:

  serializer.encoder.foo_xml:
    class: Drupal\your_custom_module\Encoder\XmlEncoder
    tags:
      - { name: encoder, format: foo_xml }

Then you can interact with your custom REST resource via http://example.com/your/custom/rest/resource?_format=foo_xml… and the root node will no longer be <response>, but <foo>.

abhishek-anand’s picture

This approached worked for me. Thanks a lot.

wim leers’s picture

Status: Postponed (maintainer needs more info) » Fixed

Great! :)

swentel’s picture

fwiw, I had this need as well, I just added an annotation on my resource and the used that in the RequestHandler which I overtook. (the things you have todo migrating from D6 services to D8 isn't always pleasant, but oh well)

wim leers’s picture

This approach will be more reliable. Formats will continue to work the same way, they're an API. A particular controller is not an API; it may change between releases (and in the case of RequestHandler, it already has, and certainly will again in the future), which means you'll need to chase changes.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

duncan.moo’s picture

For the sake of reference and assisting anyone viewing this page, XmlEncoder includes a method allowing you to change the XML root node name:

$encoder = new XmlEncoder();
$encoder->setRootNodeName('Request');
$RequestDetail = $encoder->encode([
  'Name' => 'value',
  'OtherName' => 'value'
], 'xml');

gives you:

<?xml version="1.0"?>
<Request>
  <Name>value</Name>
  <OtherName>value</OtherName>
</Request>
guilmour-asc’s picture

Worked perfectly...
But how do I add context to my new format, just like "xml_format_output" or "xml_encoding"?

bbuchert’s picture