XML to JSON in Golang Demystified
By: Keiran Smith
Tags: Openfaas, Serverless, Golang, Xml, Json

In Golang we can attack this in a number of ways like using an XML to JSON Library, but why not use the Go standard libraries and save some vendoring issues.

Building our own XML to JSON function

I was recently working on something that required a Medium RSS feed published to a website and thought why not use a GoLang function running on OpenFaaS to accomplish this.

Create a new function

To create our new function we need to use the OpenFaaS CLI

$ faas new medium2json --lang=go

Now we have a super simple Golang handler for OpenFaaS.

Import our Libraries

There are a few libraries required by our function. So let's import them. Open function/handler.go and add the imports under package

Imports!!

You will notice I added net/http so let's make use of it.

GETing our RSS Feed

Regular Medium users will know that an RSS feed is exposed for each user at https://medium.com/feed/@affix

We can utilize this feed to get what we need using a simple HTTP GET with the net/http package in Go. Let's add it to our Handle function:

The above code is pretty simple, but I always get asked about the defer statement.

What exactly can happen if you don’t defer?

The answer is pretty simple. Without defering the Close() , you create a resource leak. While the application is running, the resource used to create the request can never be closed and the file descriptor will not be released.

Do I need to Close the Request?

If the Body is not both read to EOF and closed, the Client’s underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent “keep-alive” request.

Parse that XML

Now that we have some data, we should parse it. But before we do that we need a structure to unmarshal the data into.

In the handler.go file above the function lets create a struct to match the data we require. The beauty of the GoLang unmarshal function allows us to specify in the struct only the fields we require.

If you look at the XML returned by the Medium Feed, you will notice I have omitted a lot of unnecessary fields like Channel.Title and Channel.Image so the xml.Unmarshal function will not attempt to add those fields to the struct.

You may also notice I have a Posts []struct that doesn’t appear on the RSS Feed. This comes from the items element of the XML Document specified at the end of the struct with xml:”item” the unmarshal function will take all item elements and parse them into the Posts []struct .

So let's parse that data into the struct in the Handle function:

The Unmarshal function parses the XML-encoded data and stores the result in the value pointed to by v , which must be an arbitrary struct, slice, or string. Well-formed data that does not fit into v is discarded.

Because Unmarshal uses the reflect package, it can only assign to exported fields. Unmarshal uses a case-sensitive comparison to match XML element names to tag values and struct field names.

Convert to JSON and Return

Now we have our structure we can Marshal it to JSON.

Marshal returns the JSON encoding of the input interface.

Marshal traverses the value v recursively. If an encountered value implements the Marshaler interface and is not a nil pointer, Marshal calls its MarshalJSON method to produce JSON.

Since the Marshal function produces a []byte we need to convert this to a string when returning from our Handle function using string() .

Deploy to OpenFaaS

Now we can deploy our function to our OpenFaaS cluster:

$ faas up -f medium2json.yml

$ faas up -f medium2json.yml

[0] > Building medium2json.

Clearing temporary build folder: ./build/medium2json/

Preparing ./medium2json/ ./build/medium2json//function

Building: affixxx/medium2json:latest with go template. Please wait..

Sending build context to Docker daemon 7.68kB

Once you have your function deployed you can test it using curl:

curl -X POST -d “affix” https://gateway.faas.kfj.io/function/medium2json

[{“Title”:”#FaasFriday — Building a Serverless Microblog…

The above URL is currently deployed, feel free to see the results using it.

TLDR; The Full Function Code