javaintermediate

JSON Serialization Without Libraries

Serialize and deserialize Java objects to JSON manually with a lightweight builder-based approach.

java
import java.util.*;
import java.util.stream.Collectors;

public class JsonBuilder {
    private final StringBuilder sb = new StringBuilder();
    private boolean first = true;

    public JsonBuilder startObject() { sb.append('{'); first = true; return this; }
    public JsonBuilder endObject() { sb.append('}'); return this; }
    public JsonBuilder startArray() { sb.append('['); first = true; return this; }
    public JsonBuilder endArray() { sb.append(']'); return this; }

    private JsonBuilder separator() {
        if (!first) sb.append(',');
        first = false;
        return this;
    }

    public JsonBuilder key(String key) {
        separator();
        sb.append('"').append(escape(key)).append('"').append(':');
        first = true;
        return this;
    }

    public JsonBuilder value(String val) {
        separator();
        if (val == null) sb.append("null");
        else sb.append('"').append(escape(val)).append('"');
        return this;
    }

    public JsonBuilder value(Number val) { separator(); sb.append(val); return this; }
    public JsonBuilder value(boolean val) { separator(); sb.append(val); return this; }
    public JsonBuilder nullValue() { separator(); sb.append("null"); return this; }

    private String escape(String s) {
        return s.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\t", "\\t");
    }

    @Override
    public String toString() { return sb.toString(); }

    // Convenience: object to JSON
    public static String toJson(Map<String, Object> map) {
        JsonBuilder jb = new JsonBuilder();
        jb.startObject();
        map.forEach((k, v) -> {
            jb.key(k);
            writeValue(jb, v);
        });
        jb.endObject();
        return jb.toString();
    }

    @SuppressWarnings("unchecked")
    private static void writeValue(JsonBuilder jb, Object v) {
        if (v == null) jb.nullValue();
        else if (v instanceof String s) jb.value(s);
        else if (v instanceof Number n) jb.value(n);
        else if (v instanceof Boolean b) jb.value(b);
        else if (v instanceof Map<?,?> m) {
            jb.startObject();
            ((Map<String, Object>) m).forEach((k, val) -> {
                jb.key(k); writeValue(jb, val);
            });
            jb.endObject();
        }
        else if (v instanceof List<?> list) {
            jb.startArray();
            list.forEach(item -> writeValue(jb, item));
            jb.endArray();
        }
    }

    public static void main(String[] args) {
        // Builder API
        String json = new JsonBuilder()
            .startObject()
                .key("name").value("Alice")
                .key("age").value(30)
                .key("active").value(true)
                .key("scores").startArray()
                    .value(95).value(87).value(92)
                .endArray()
            .endObject()
            .toString();
        System.out.println(json);

        // Map API
        String fromMap = toJson(Map.of(
            "status", "ok",
            "count", 42,
            "items", List.of("a", "b", "c")
        ));
        System.out.println(fromMap);
    }
}

Use Cases

  • Lightweight JSON generation without Jackson/Gson
  • Embedded systems or minimal dependency projects
  • Custom serialization for specific formats

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.