How to set up XML in Grape API

Want to integrate XML into your Grape API project? XML (eXtensible Markup Language) is a widely used data format that allows structured representation and exchange of information between different systems. By adding XML support to your Grape API, you can enable seamless communication with XML-based clients and take advantage of its flexibility and compatibility. In this article, we will explore the step-by-step process of setting up XML in Grape API, enabling you to efficiently handle XML data within your API endpoints.

Enable additional content type

Firstly, we have to enable additional permitted `content_type' for our API.

module Api
  module V1
    class Products < Base
      content_type :json, 'application/json'
      default_format :json
      
      # accept XML output
      content_type :xml, 'application/xml'

      resources :products do
        desc 'Get all products'
        get do
          Product.all.map { |product| ::Products::Presenters::Basic.call(product) }
        end
      end
    end
  end
end

We need to enable additional accepted content_type for our API, which will do the trick, but when we test this thing in practice it will print a weird root key for the XML output like {"hash"=>{" or {"objects"=>[{".

How to change root name for XML output

So we need to edit this root somehow, for example I want to have product when hash and products when objects. Let's edit the formatter a bit.

formatter :xml, lambda { |object, _env| object.to_xml(root: object.is_a?(Hash) ? 'product' : 'products') }
If hash, please print product. If something else, I want to see products as root key

Now we have a similar output style as for JSON output. Here is the complete solution, which can be reused in more generic classes like configuration class, etc.

module Api
  module V1
    class Products < Base
      content_type :json, 'application/json'
      content_type :xml, 'application/xml'
      default_format :json

      # change root type from Object/Hash/Array to product/products for XML output
      formatter :xml, lambda { |object, _env| object.to_xml(root: object.is_a?(Hash) ? 'product' : 'products') }

      resources :products do
        desc 'Get all products'
        get do
          Product.all.map { |product| ::Products::Presenters::Basic.call(product) }
        end
      end
    end
  end
end

We can see that adding XML to Grape is quite simple. We only need a few lines in our configuration.

Happy coding!