Making a RESTful JSON API in Go – InApps is an article under the topic Software Development Many of you are most interested in today !! Today, let’s InApps.net learn Making a RESTful JSON API in Go – InApps in today’s post !

Read more about Making a RESTful JSON API in Go – InApps at Wikipedia



You can find content about Making a RESTful JSON API in Go – InApps from the Wikipedia website

In this post, we will not only cover how to use Go to create a RESTful JSON API, but we will also talk about good RESTful design. If you have ever consumed an API in the past that doesn’t follow good design, then you end up writing bad code to consume a bad API. Hopefully, after this article you will have a better idea of what a well behaved API should look like.

What is a JSON API?

Before JSON, there was XML. Having used XML and JSON both, there is no question that JSON is the clear winner. I’m not going to cover in depth the concept of a JSON API, as it is detailed quite well on jsonapi.org.

A Basic Web Server

A RESTful service starts with fundamentally being a web service first. Here is a really basic web server that responds to any requests by simply outputting the request url:

Running this example will spin up a server on port 8080, and can be accessed at http://localhost:8080

Adding a Router

While the standard library comes with a router, I find that most people are confused about how it works. I’ve used a couple of third party routers in my projects. Most notably I’ve used the mux router from the Gorilla Web Toolkit.

Another popular router is from Julien Schmidt called httprouter.

To run this example, you will now need to execute the following command:

This will retrieve the Gorilla Mux package from GitHub at “github.com/gorilla/mux”

The above example creates a basic router, adds the route / and assigns the Index handler to run when that endpoint is called. You will also notice now that before we could ask for http://localhost:8080/foo and that worked. That will no longer work now as there is no route defined. Only http://localhost:8080 will be a valid response.

Creating Some Basic Routes

Now that we have a router in place, it is time to create some more routes.

Let’s assume that we are going to create a basic ToDo app.

We have now added two more endpoints (or routes)

This is the Todo Index route: http://localhost:8080/todos

THis is the Todo Show route: http://localhost:8080/todos/{todoId}

This is the beginning of a RESTful design.

Pay close attention to the last route where we added a variable in the route, called todoId: http://localhost:8080/todos/{todoId}

This will allow us to pass in id’s to the route and respond with the proper records.

A Basic Model

Now that we have routes in place, it’s time to create a basic Todo model that we can send and retrieve data with. In Go, a struct will typically serve as your model. Many other languages use classes for this purpose.

Note that in the last line we create another type, called Todos, which is a slice (an ordered collection) of Todo. You will see where this becomes useful shortly.

Read More:   The Challenges of Making Video Games for Cats – InApps 2022

Send Back Some JSON

Now that we have a basic model, we can simulate a real response and mock out the TodoIndex with static data.

For now, we are just creating a static slice of Todos to send back to the client. Now if you requesthttp://localhost:8080/todos, you should get the following response:

A Better Model

For any seasoned veterans out there, you have already spotted a problem. As insignificant as it sounds, it’s not idiomatic JSON to have uppercased keys. Here is how you solve that.

By adding struct tags you can control exactly what an how your struct will be marshalled to JSON.

OK, We Need to Split This Up!

At this point, the project needs a little refactoring. We have too much going on in just a few files.

We are going to now create the following files and move the code around accordingly:

  • main.go
  • handlers.go
  • routes.go
  • todo.go

Handlers.go

Routes.go

Todo.go

Main.go

Even Better Routing

As part of our refactoring, we created a much more versatile routes file. This new file now utilizes a struct to contain more detailed information about the route. Specifically, we can now specify the action, such as GET, POST, DELETE, etc.

Outputting a Web Log

In splitting up the routes file, I also had an ulterior motive. As you will see shortly, it now becomes very easy to decorate my http handlers with additional functionality.

Let’s start with the ability to log out web requests like most modern web servers do. In Go, there is no web logging package or functionality in the standard library, so we have to create it.

We’ll do that by creating a file called logger.go and add the following code:

This is a very standard idiom in Go. Effectively we are going to pass our handler to this function, which will then wrap the passed handler with logging and timing functionality.

Read More:   Was Parler Really a Progressive Web App? – InApps 2022

Next, we will need to utilize the logger decorator in our routes.

Applying the Logger Decorator

To apply the decorator, when we create the router, we will simply wrap all our current routes in it by updating our NewRouter function:

Now, when you request http://localhost:8080/todos you should see something like this logged at the console:

This Routes File is Crazy … Let’s Refactor

Now that the routes file has gotten a little larger, let’s split it to the following files:

Routes.go – redux

Router.go

Taking Some Responsibility

Now that we have some pretty good boilerplate, it’s time to revisit our handlers. We need to be a little more responsible. We will first modify the TodoIndex by adding two lines of code:

Two things are now happening. First, we are sending back our content type and telling the client to expect json. Second, we are explicitly setting the status code.

Go’s net/http server would have tried to guess the output content type for us (it isn’t always accurate however), but since we definitively know the type, we should always set it ourselves.

Wait, Where is my Database?

Clearly if we are going to create a RESTful API, we would need somewhere to store and retrieve data. However, that is beyond the scope of this article, so we will simply create a very crude (and not thread safe) mock database.

Create a file called repo.go and add the following content:

Add ID to Todo

Now that we have a “mock” database, we are using and assigning id, so we will have to update our Todo struct accordingly.

Update our TodoIndex

To use the database, we will need to now retrieve the data in our TodoIndex by modifying the following function:

Posting JSON

So far, we have only output JSON, now it’s time to take in and store some JSON.

Add the following route to the routes.go file:

The Create endpoint

Now we have to add the create endpoint to the handlers file.

The first thing we do is open up the body of the request. Notice that we use io.LimitReader. This is a good way to protect against malicious attacks on your server. Imagine if someone wanted to send you 500GBs of json!

After we have read the body, we then Unmarshal it to our Todo struct. If that fails, we will do the right thing and not only respond with the appropriate status code, 422, but we will also send back the error in a json string. This will allow the client to understand not only that something went wrong, but we have the ability to communicate specifically what went wrong.

Finally, if all has gone well, we send back the status code of 201, which means that the entity was successfully created. We also send back the json representation of entity we created, as it contains an id that the client will likely need for their next step.

Post some JSON

Now that we have our fake repo and our “create” endpoint, it’s time to post some data. I use curl to do so via the following command:

Things We Didn’t Do

While we are off to a great start, there is a lot left to do. Things we haven’t addressed are:

  • Version Control – What if we need to modify the API and that results in a breaking change? Might we add /v1/prefix to all our routes to start with?
  • Authentication – Unless this is a free/public API, we probably need some authentication. I suggest learning about JSON web tokens

eTags – If you are building something that needs to scale, you will likely need to implement eTags

What Else is Left?

As with all projects, things start off small but can quickly spiral out of control. If I was going to take this to the next level and make it production ready, these are just some of the additional things to do:

  • Lots of refactoring!
  • Create packages for several of these files, such as some JSON helpers, decorators, handlers, and more.
  • Testing… oh yes, you can’t forget that. We didn’t do ANY testing here. For a production system, this is a must.

Can I get the Code?

Yes! Here is a repo with all of the code samples used in this post:

https://github.com/corylanou/tns-restful-json-api

Summary

The most important thing to me is to remember to be build a responsible API. Sending back proper status codes, content headers, etc is critical to having your API widely adopted. I hope this post gets you started on your own API soon!

Cory LaNou is an experienced software developer with over two decades of experience, and two and a half years of production Go experience. He is currently a lead instructor at gSchool where he teaches Go and leads the local Denver Go meetup, aptly called Denver Gophers.

Feature image from Startupitis. The image is available on the site to download as wallpaper.




Source: InApps.net

Rate this post
As a Senior Tech Enthusiast, I bring a decade of experience to the realm of tech writing, blending deep industry knowledge with a passion for storytelling. With expertise in software development to emerging tech trends like AI and IoT—my articles not only inform but also inspire. My journey in tech writing has been marked by a commitment to accuracy, clarity, and engaging storytelling, making me a trusted voice in the tech community.

Let’s create the next big thing together!

Coming together is a beginning. Keeping together is progress. Working together is success.

Let’s talk

Get a custom Proposal

Please fill in your information and your need to get a suitable solution.

    You need to enter your email to download

      Success. Downloading...