package com.googlecode.d2j.ai; /** * Minimal dependency-free JSON builder shared by the analysis commands. * *

The analysis commands historically each hand-rolled their own {@code jsonStr} * escaper and string concatenation. This class centralizes escaping and provides a * tiny fluent object/array builder so every command emits identical, well-formed JSON. * *

Output is compact (no pretty-printing); the Python wrapper / MCP layer re-formats * when a human-readable view is requested. * *

{@code
 * String out = Json.obj()
 *     .put("count", 3)
 *     .putRaw("items", Json.arr().add("a").add("b").build())
 *     .build();
 * }
*/ public final class Json { private Json() { } /** Quote and escape a string value, or return the literal {@code null}. */ public static String str(String s) { if (s == null) { return "null"; } StringBuilder sb = new StringBuilder(s.length() + 2); sb.append('"'); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '"': sb.append("\\\""); break; case '\\': sb.append("\\\\"); break; case '\n': sb.append("\\n"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; default: if (c < 0x20) { sb.append(String.format("\\u%04x", (int) c)); } else { sb.append(c); } } } sb.append('"'); return sb.toString(); } public static Obj obj() { return new Obj(); } public static Arr arr() { return new Arr(); } /** Fluent JSON object builder. */ public static final class Obj { private final StringBuilder sb = new StringBuilder("{"); private boolean first = true; private void key(String k) { if (!first) { sb.append(','); } first = false; sb.append(Json.str(k)).append(':'); } /** Add a string-valued field (value is escaped/quoted). */ public Obj put(String k, String v) { key(k); sb.append(Json.str(v)); return this; } public Obj put(String k, long v) { key(k); sb.append(v); return this; } public Obj put(String k, boolean v) { key(k); sb.append(v); return this; } /** Add a field whose value is already-serialized JSON (object, array, number…). */ public Obj putRaw(String k, String rawJson) { key(k); sb.append(rawJson); return this; } public String build() { return sb.toString() + "}"; } } /** Fluent JSON array builder. */ public static final class Arr { private final StringBuilder sb = new StringBuilder("["); private boolean first = true; private void sep() { if (!first) { sb.append(','); } first = false; } /** Add a string element (escaped/quoted). */ public Arr add(String v) { sep(); sb.append(Json.str(v)); return this; } public Arr add(long v) { sep(); sb.append(v); return this; } /** Add an already-serialized JSON element. */ public Arr addRaw(String rawJson) { sep(); sb.append(rawJson); return this; } public boolean isEmpty() { return first; } public String build() { return sb.toString() + "]"; } } }