×

Conclusion

Last Updated: December 13, 2023

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!

Start Free with
Starburst Galaxy

Up to $500 in usage credits included

  • Query your data lake fast with Starburst's best-in-class MPP SQL query engine
  • Get up and running in less than 5 minutes
  • Easily deploy clusters in AWS, Azure and Google Cloud
For more deployment options:
Download Starburst Enterprise

Please fill in all required fields and ensure you are using a valid email address.

s