Conclusion

  • Jordan Zimmerman

    Jordan Zimmerman

    Staff Software Engineer

    Starburst

Share

This is part 7 of the Bleeding edge Java series. Start at the introduction if you haven’t already.

We now have the beginnings of a modern JSON serialization library. The full featured version of this library can be found on GitHub. Let’s summarize what we achieved together.

First, let’s make one last helper to simplify the usage of the library. We’ll create a high level API for our library that exposes methods that are easier to use.

public interface Json
{
    String serializeToString(Object o);

    void serializeToWriter(Object o, Writer writer);

    <T> T deserialize(TypeToken<T> type, String json);

    <T> T deserialize(Class<T> type, String json);

    <T> T deserialize(TypeToken<T> type, Reader reader);

    <T> T deserialize(Class<T> type, Reader reader);
}

The implementation for it is straightforward:

new Json() {
    private final JsonPrinter printer = JsonPrinter.instance();
    private final JsonParser parser = JsonParser.instance();
    private final JsonDeserializer deserializer = JsonDeserializer.instance();
    private final JsonSerializer serializer = JsonSerializer.instance();

    @Override
    public String serializeToString(Object o)
    {
        return serializer.serialize(o)
                .map(printer::print)
                .collect(Collectors.joining());
    }

    @Override
    public void serializeToWriter(Object o, Writer writer)
    {
        serializer.serialize(o)
                .map(printer::print)
                .forEach(str -> {
                    try {
                        writer.append(str);
                    }
                    catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                });
    }
    
    @Override
    public <T> T deserialize(TypeToken<T> type, String json)
    {
        return deserialize(type.type(), json);
    }

    @Override
    public <T> T deserialize(TypeToken<T> type, Reader reader)
    {
        return deserialize(type.type(), reader);
    }

    @Override
    public <T> T deserialize(Class<T> type, String json)
    {
        return deserialize((Type) type, json);
    }

    @Override
    public <T> T deserialize(Class<T> type, Reader reader)
    {
        return deserialize((Type) type, reader);
    }

    @SuppressWarnings("unchecked")
    private <T> T deserialize(Type type, String json)
    {
        return (T) parser.parse(json.chars())
                .collect(JsonDeserializerCollector.deserializing(deserializer, type));
    }

    @SuppressWarnings("unchecked")
    private <T> T deserialize(Type type, Reader reader)
    {
        BufferedReader bufferedReader = new BufferedReader(reader);
        return (T) parser.parse(bufferedReader.lines().flatMapToInt(String::chars))
                .collect(JsonDeserializerCollector.deserializing(deserializer, type));
    }
};

Test it out for yourself!

Let’s try the high-level API to serialize and deserialize in jshell. This example will use these files:

From a terminal with Java 19 installed, run the following (note you’ll need the wget utility):

wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/TypeToken.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonToken.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonSerializer.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/StringUtils.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonPrinter.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonParser.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonDeserializer.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/JsonDeserializerCollector.java
wget -nc https://raw.githubusercontent.com/starburstdata/developer-blog-assets/main/bleeding-edge-java/code/Json.java
jshell --enable-preview TypeToken.java JsonToken.java JsonSerializer.java StringUtils.java JsonPrinter.java JsonParser.java JsonDeserializer.java JsonDeserializerCollector.java Json.java

Try the following example or create your own.

var json = Json.instance();

enum Suit { Diamonds, Clubs, Spades, Hearts };
record Value(String name, int value) {}
record Card(Value value, Suit suit) {}
TypeToken<List<Card>> typeToken = new TypeToken<>() {};

List<Card> straight = List.of(
    new Card(new Value("A", 1), Suit.Spades), 
    new Card(new Value("2", 2), Suit.Diamonds),
    new Card(new Value("3", 3), Suit.Clubs),
    new Card(new Value("4", 4), Suit.Hearts),
    new Card(new Value("5", 5), Suit.Diamonds));

String straightJson = json.serializeToString(straight);
List<Card> deserializedStraight = json.deserialize(typeToken, straightJson);

System.out.println();
System.out.println("RESULTS");
System.out.println("straight.equals(deserializedStraight)?");
System.out.println(straight.equals(deserializedStraight));
System.out.println();
System.out.println("JSON text:");
System.out.println();
System.out.println(straightJson);

Summary

We have a simple JSON library and have learned about the very latest features of Java. We hope you’ve enjoyed this series. Look forward to future posts that explore modern topics in software development.

We’re hiring

Want to be able to use the latest features of Java? We’re hiring!