package vn.sis.appointment; import java.util.Collection; import java.util.Map; final class Json { private Json() { } static String stringify(Object value) { if (value == null) { return "null"; } if (value instanceof String text) { return quote(text); } if (value instanceof Number || value instanceof Boolean) { return value.toString(); } if (value instanceof Map map) { StringBuilder builder = new StringBuilder("{"); boolean first = true; for (Map.Entry entry : map.entrySet()) { if (!first) { builder.append(','); } first = false; builder.append(quote(String.valueOf(entry.getKey()))) .append(':') .append(stringify(entry.getValue())); } return builder.append('}').toString(); } if (value instanceof Collection collection) { StringBuilder builder = new StringBuilder("["); boolean first = true; for (Object item : collection) { if (!first) { builder.append(','); } first = false; builder.append(stringify(item)); } return builder.append(']').toString(); } return quote(value.toString()); } static String quote(String value) { StringBuilder builder = new StringBuilder(value.length() + 16).append('"'); for (int i = 0; i < value.length(); i++) { char ch = value.charAt(i); switch (ch) { case '"' -> builder.append("\\\""); case '\\' -> builder.append("\\\\"); case '\b' -> builder.append("\\b"); case '\f' -> builder.append("\\f"); case '\n' -> builder.append("\\n"); case '\r' -> builder.append("\\r"); case '\t' -> builder.append("\\t"); default -> { if (ch < 0x20) { builder.append(String.format("\\u%04x", (int) ch)); } else { builder.append(ch); } } } } return builder.append('"').toString(); } }