import static java.util.Map.entry; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; sealed interface Json { enum JsonNull implements Json { NULL } enum JsonBoolean implements Json { TRUE, FALSE } record JsonString(String value) implements Json {} record JsonNumber(Number value) implements Json {} record JsonObject(Map<String, Json> value) implements Json {} record JsonArray(List<Json> value) implements Json {} default String asString() { return switch (this) { case JsonNull _ -> "null"; case JsonBoolean b -> switch (b) { case TRUE -> "true"; case FALSE -> "false"; }; case JsonString(var value) -> "\"" + value + "\""; case JsonNumber(var value) -> String.valueOf(value); case JsonObject(var map) -> map.entrySet().stream() .map(entry -> "\"" + entry.getKey() + "\":" + entry.getValue().asString()) .collect(joining(",", "{", "}")); case JsonArray(var array) -> array.stream() .map(Json::asString) .collect(joining(",", "[", "]")); }; } static Json string(String value) { return new JsonString(value); } static Json number(Number value) { return new JsonNumber(value); } static Json array(Json...elements) { return new JsonArray(List.of(elements)); } @SafeVarargs static Json object(Map.Entry<String, Json>...entries) { return new JsonObject(Stream.of(entries) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue))); } static void main() { var json = array( object(entry("name", string("Toni")), entry("age", number(46)), entry("old", JsonBoolean.TRUE)), object(entry("name", string("Baby")), entry("age", JsonNull.NULL), entry("old", JsonBoolean.FALSE)) ); System.out.println(json.asString()); } }