Greg Liles
Greg Liles

Reputation: 31

How to produce/consume XML using swagger-node

I'm new at using swagger-node (swagger-spec 2.0) and I have a need for my API to consume and produce both XML and JSON (because that's what the customer wants). Currently I have only focused on the "produce" part.

When producing a response, I know I can turn my js object into XML using tools such as jstoxml or easyxml. So the question is: is this necessary when using swagger-node or are the tools suppose to handle this? I guess I need help in what my controller code should return.

For example, create a new project using swagger swagger project create myproject (choose express framework)

Change the yaml file for the /hello api so that get: returns both json or xml

paths:
  /hello:
    # binds a127 app logic to a route
    x-swagger-router-controller: hello_world
    get:
      description: Returns 'Hello' to the caller
      # used as the method name of the controller
      operationId: hello
      produces:
        - application/json
        - application/xml

Then change the hello_world.js controller to return a json object instead of a string

  // variables defined in the Swagger document can be referenced using req.swagger.params.{parameter_name}
  var name = req.swagger.params.name.value || 'stranger';
  var hello = util.format('Hello, %s!', name);

  // this sends back a JSON response which is a single string
  res.json({message:hello});
}

When I start the project and use Postman with Header Accept = application/json I get the response:

{
    "message": "Hello, stranger!"
}

If I change the Header Accept application/xml, I still get the JSON response, not XML. What I was hoping to see is:

<object>
<message>Hello, stranger!</message>
</object>

I know my code is wrong to use res.json() because I believe it sets the Content-Type to application/json.

I don't know what else to use to produce the XML response. When I change out the res.json() to use easyxml

var xml = easyxml.render({message:hello});
res.type('xml').end(xml);

I then get a validation error from swagger:

[
  {
    "status": 500,
    "message": "Response validation failed: value expected to be an array/object but is not"
  }
]

So how should my controller be formatting the response to return either XML or JSON?

Upvotes: 3

Views: 3230

Answers (2)

brandonscript
brandonscript

Reputation: 73034

I'm not exactly sure what easyxml is doing or why it's not working, but jstoxml works great:

var jstoxml = require('jstoxml');
var express = require('express');
var util = require('util');
var app = express();

app.get('/', function(req, res) {
    var name = 'stranger';
    var hello = {
        object: {
            message: util.format('Hello, %s!', name)
        }
    };
    if (req.headers.accept === 'application/xml') {
        res.type('xml')
        res.end(jstoxml.toXML(hello));
    } else {
        res.json(hello);
    }
});

app.listen(process.env.PORT || 8100);

Accept: application/json

{
    "object": 
    {
        "message": "Hello, stranger!"
    }
}

Accept: application/xml

<object>
    <message>Hello, stranger!</message>
</object>

Upvotes: 1

maurizio butti
maurizio butti

Reputation: 1

Apparently there is no correct way. remus' answer does not take into account Swagger explicit XML support. In any case the controller should definitely not mess with the API i/o formats, but just implement business logic.

Upvotes: 0

Related Questions