Json in Fortress

Here’s the translation of the JSON example from Go to Java, formatted in Markdown suitable for Hugo:

Our example will demonstrate JSON encoding and decoding in Java, including handling custom data types.

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;

// We'll use these two classes to demonstrate encoding and
// decoding of custom types below.
class Response1 {
    public int page;
    public List<String> fruits;
}

// Fields must be public or have getter/setter methods to be serialized/deserialized.
class Response2 {
    @JsonProperty("page")
    public int page;
    
    @JsonProperty("fruits")
    public List<String> fruits;
}

public class JsonExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // First we'll look at encoding basic data types to
        // JSON strings. Here are some examples for atomic values.
        System.out.println(mapper.writeValueAsString(true));
        System.out.println(mapper.writeValueAsString(1));
        System.out.println(mapper.writeValueAsString(2.34));
        System.out.println(mapper.writeValueAsString("gopher"));

        // And here are some for slices and maps, which encode
        // to JSON arrays and objects as you'd expect.
        List<String> slcD = List.of("apple", "peach", "pear");
        System.out.println(mapper.writeValueAsString(slcD));

        Map<String, Integer> mapD = Map.of("apple", 5, "lettuce", 7);
        System.out.println(mapper.writeValueAsString(mapD));

        // The Jackson library can automatically encode your
        // custom data types.
        Response1 res1D = new Response1();
        res1D.page = 1;
        res1D.fruits = List.of("apple", "peach", "pear");
        System.out.println(mapper.writeValueAsString(res1D));

        // You can use annotations on class field declarations
        // to customize the encoded JSON key names. Check the
        // definition of Response2 above to see an example
        // of such annotations.
        Response2 res2D = new Response2();
        res2D.page = 1;
        res2D.fruits = List.of("apple", "peach", "pear");
        System.out.println(mapper.writeValueAsString(res2D));

        // Now let's look at decoding JSON data into Java
        // objects. Here's an example for a generic data
        // structure.
        String byt = "{\"num\":6.13,\"strs\":[\"a\",\"b\"]}";

        // We need to provide a type where the Jackson
        // library can put the decoded data. This
        // Map<String, Object> will hold a map of strings
        // to arbitrary data types.
        Map<String, Object> dat = mapper.readValue(byt, Map.class);
        System.out.println(dat);

        // In order to use the values in the decoded map,
        // we'll need to convert them to their appropriate type.
        // For example here we convert the value in num to
        // the expected Double type.
        Double num = (Double) dat.get("num");
        System.out.println(num);

        // Accessing nested data requires a series of
        // conversions.
        List<String> strs = (List<String>) dat.get("strs");
        String str1 = strs.get(0);
        System.out.println(str1);

        // We can also decode JSON into custom data types.
        // This has the advantages of adding additional
        // type-safety to our programs and eliminating the
        // need for type casts when accessing the decoded
        // data.
        String str = "{\"page\": 1, \"fruits\": [\"apple\", \"peach\"]}";
        Response2 res = mapper.readValue(str, Response2.class);
        System.out.println(res.page);
        System.out.println(res.fruits.get(0));

        // In the examples above we always used strings as
        // intermediates between the data and JSON representation.
        // We can also stream JSON encodings directly to
        // OutputStream like System.out or even HTTP response bodies.
        mapper.writeValue(System.out, mapD);
    }
}

To run this program, you’ll need to include the Jackson library in your project. You can do this by adding the following dependency to your pom.xml if you’re using Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

Or by downloading the JAR files and including them in your classpath.

When you run this program, you should see output similar to the following:

true
1
2.34
"gopher"
["apple","peach","pear"]
{"apple":5,"lettuce":7}
{"page":1,"fruits":["apple","peach","pear"]}
{"page":1,"fruits":["apple","peach","pear"]}
{num=6.13, strs=[a, b]}
6.13
a
1
apple
{"apple":5,"lettuce":7}

We’ve covered the basics of JSON in Java here, but check out the Jackson documentation for more detailed information and advanced features.