Oskar
Oskar

Reputation: 43

Return JSON response in ISO-8859-1 with NodeJS/Express

I have built an API with Node and Express which returns some JSON. The JSON data is to be read by a web application. Sadly this application only accepts ISO-8859-1 encoded JSON which has proven to be a bit difficult.

I can't manage to return the JSON with the right encoding even though I've tried the methods in the Express documentation and also all tips from googling the issue.

The Express documentation says to use "res.set()" or "res.type()" but none of these is working for me. The commented lines are all the variants that I've tried (using Mongoose):

MyModel.find()
.sort([['name', 'ascending']])
.exec((err, result) => {
  if (err) { return next(err) }

  // res.set('Content-Type', 'application/json; charset=iso-8859-1')
  // res.set('Content-Type', 'application/json; charset=ansi')
  // res.set('Content-Type', 'application/json; charset=windows-1252')
  // res.type('application/json; charset=iso-8859-1')
  // res.type('application/json; charset=ansi')
  // res.type('application/json; charset=windows-1252')

  // res.send(result)
  res.json(result)
})

None of these have any effect on the response, it always turns into "Content-Type: application/json; charset=utf-8".

Since JSON should(?) be encoded in utf-8, is it event possible to use any other encoding with Express?

Upvotes: 3

Views: 2985

Answers (1)

ottomeister
ottomeister

Reputation: 5808

If you look at the lib/response.js file in the Express source code (in your node_modules folder or at https://github.com/expressjs/express/blob/master/lib/response.js) you'll see that res.json takes your result, generates the corresponding JSON representation in a JavaScript String, and then passes that string to res.send.

The cause of your problem is that when res.send (in that same source file) is given a String argument, it encodes the string as UTF8 and also forces the charset of the response to utf-8.

You can get around this by not using res.json. Instead build the encoded response yourself. First use your existing code to set up the Content-Type header:

    res.set('Content-Type', 'application/json; charset=iso-8859-1')

After that, manually generate the JSON string:

    jsonString = JSON.stringify(result);

then encode that string as ISO-8859-1 into a Buffer:

    jsonBuffer = Buffer.from(jsonString, 'latin1');

Finally, pass that buffer to res.send:

    res.send(jsonBuffer)

Because res.send is no longer being called with a String argument, it should skip the step where it forces charset=utf-8 and should send the response with the charset value that you specified.

Upvotes: 3

Related Questions