Posting and Responding with JSON

The next behavior we want to create will demonstrate how to parse and respond with JSON (as REST APIs tend to do).

Our goal is simple: A request contains JSON with a name, age, and money. We want to take those 3 fields, add $5000 to money and 10 years to age, and return a nicely formatted JSON response.

Getting Old and Rich(er)

Just like we did before, create a new behavior named AboutBehavior inside the behaviors package. Add the following content:

behaviors/AboutBehavior.java
package com.ociweb.behaviors;

import com.ociweb.HelloField;
import com.ociweb.gl.api.GreenRuntime;
import com.ociweb.gl.api.HTTPRequestReader;
import com.ociweb.gl.api.HTTPResponseService;
import com.ociweb.gl.api.RestListener;
import com.ociweb.json.encode.JSONRenderer;
import com.ociweb.pronghorn.network.config.HTTPContentTypeDefaults;
import com.ociweb.pronghorn.pipe.StructuredReader;

public class AboutBehavior implements RestListener {
    private HTTPResponseService responseService;

    // Our 3 fields: 
    private int money;
    private int age;
    private String name;

    public AboutBehavior(GreenRuntime runtime) {
        responseService = runtime.newCommandChannel().newHTTPResponseService();
    }

    @Override
    public boolean restRequest(HTTPRequestReader request) {
    }
}

Similar to HelloBehavior, we have our responseService object. However, you will notice the addition of 3 new variables which will contain the fields we want to keep track of and edit.

Generating JSON with GreenLightning is built-in and very easy. First, add the following code below line 18 and above the constructor:

behaviors/AboutBehavior.java
private static final JSONRenderer<AboutBehavior> jsonRenderer = new JSONRenderer<AboutBehavior>()
        .beginObject()
                .string("msg", (o,t) -> t.append("We made ").append(o.name).append(" 10 years older and $5000 richer."))
                .integer("money", o -> o.money )
                .integer("age", o -> o.age )
                .string("name", (o,t)-> t.append(o.name) )
        .endObject();
  • We create a new JSONRenderer object creatively named jsonRenderer. Its generic type is set to the instance of the current behavior because it will contain the 3 fields required by the JSON generation.

  • beginObject() and endObject() insert the JSON curly brackets beginning and ending.

  • Then, we create 4 new keys with their corresponding types and values.

  • For the msg key, the name is appended to a templated message. For the integers money and age, no (o,t) is required since we do not need any text concatenation.

Next, we need to actually use the renderer to output our response. To do this, let's edit the restRequest method:

behaviors/AboutBehavior.java
@Override
public boolean restRequest(HTTPRequestReader request) {
    if(!request.isVerbPost()) {
        return responseService.publishHTTPResponse(request, 404);
    }       
    StructuredReader record = request.structured();

    name = record.readText(HelloField.NAME);
    age = record.readInt(HelloField.AGE) + 10;
    money = record.readInt(HelloField.MONEY) + 5000;

    return responseService.publishHTTPResponse(request, 200,
            HTTPContentTypeDefaults.JSON, w -> {
                jsonRenderer.render(w, this);
            });
}
  • On line 3, we make sure that the request is a POST request.

  • On line 6, just like we did with HelloBehavior, we create a record from the request.

  • On line 8-10, we fetch the fields from the posted JSON inside the request and add 10 to age and 5000 to money.

  • On line 12, we publish a successful response and set the content type to JSON.

    • Instead of writing directly to the writer, we call the render method on our previous jsonRenderer object and pass in the writer as well as the current behavior containing our updated variables. This will automatically respond with a correctly formatted JSON.

Don't forget to register our new behavior inside RestServer again:

RestServer.java
@Override
public void declareBehavior(GreenRuntime runtime) {
    runtime.addRestListener(new HelloBehavior(runtime))
            .includeRoutesByAssoc(HelloStruct.HELLO_WORLD);
    runtime.addRestListener(new AboutBehavior(runtime))
            .includeRoutesByAssoc(HelloStruct.ABOUT);
}

Test your Server

Start the server again and use Postman to send a POST request to the endpoint /api/about with a JSON body that like this:

Request
{
    "name": "John",
    "age": 40,
    "money": 10000
}

You will receive the following response:

Response
{
    "msg": "We made John 10 years older and $5000 richer.",
    "money": 15000,
    "age": 50
}

This concludes this tutorial. Please refer to the Comprehensive Start Guide or other parts of this documentation for more help.

Last updated