webapi icon indicating copy to clipboard operation
webapi copied to clipboard

application/xml ContentType example

Open jmn opened this issue 8 years ago • 4 comments

How'd you use this package to build a client for an API that responds in XML?

jmn avatar Nov 17 '16 09:11 jmn

For any data format, a data type needs to be defined representing that format. Furthermore Accept, Decode and Encode instances have to be provided.

If you look in the module WebApi.ContentTypes there are implementations of JSON, HTML etc. XML has to be implemented in a similar fashion. I have written a small example with support for a XML format in WebApi, which could be adapted to your needs. Let me know if you have any more further questions.

ersran9 avatar Nov 17 '16 14:11 ersran9

We will soon bring in XML data type into the WebApi.ContentTypes. But still Encode and Decode instances will have to be provided.

ersran9 avatar Nov 17 '16 14:11 ersran9

Thank you for taking the time to provide the example, much appreciated.

-- Skipping definitions
instance Encode XML () where
  encode = undefined 

instance Decode XML () where
  decode = undefined 

I'm afraid I don't see how to implement these.

jmn avatar Nov 18 '16 21:11 jmn

I have updated the gist with missing definitions. Please note that there is no standard way of encoding to XML from data types. The user is free to use any style (by giving the instances of Encode and Decode for their types). WebApi library does not make any opinionated stand on this.

In the gist, I have used a style where field names form the tags and values come inside them. You can see the encodings and decodings in a repl session. Download the gist and in that directory run

> stack --resolver=lts-7.8 ghci --package "webapi" --package "xml-conduit"
Prelude> :l XmlExample.hs
[1 of 1] Compiling Main             ( XmlExample.hs, interpreted )
Ok, modules loaded: Main.
*Main> import Blaze.ByteString.Builder
*Main Blaze.ByteString.Builder> :set -XOverloadedStrings
*Main Blaze.ByteString.Builder> toLazyByteString (encodePersonToXML (Person "name" (Age 10) "address"))
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><PERSON><NAME>name</NAME><AGE>10</AGE><ADDRESS>address</ADDRESS></PERSON>"
*Main Blaze.ByteString.Builder> decodePersonFromXML "<?xml version=\"1.0\" encoding=\"UTF-8\"?><PERSON><NAME>name</NAME><AGE>10</AGE><ADDRESS>address</ADDRESS></PERSON>"
Right (Person {name = "name", age = Age {getAge = 10}, address = "address"})

The reason why () instances have to be provided is, by default the ApiErr gets defaulted to ().

PS: Not sure if you are aware of this, but you can see the whole code in action by

> chmod +x ./XmlExample
> ./XmlExample

ersran9 avatar Nov 21 '16 11:11 ersran9