class Json {

    public static RootNode create() {
        return new RootNode();
    }

    public interface Node<T extends Node<T>> {
        NotRootNode<T> object(String name);

        T number(String name, int value);
    }

    public static class RootNode extends AbstractNode<RootNode> implements Node<RootNode> {

        public RootNode() {
            super(new StringBuilder());
            buf.append("{");
        }

        public String build() {
            if (isNotEmpty)
                buf.setLength(buf.length() - 1);
            buf.append("}");
            return buf.toString();
        }
    }

    public static class NotRootNode<P extends Node<P>> extends AbstractNode<NotRootNode<P>> implements Node<NotRootNode<P>> {

        private final P parent;

        public NotRootNode(StringBuilder buf, P parent) {
            super(buf);
            this.parent = parent;
        }

        public P end() {
            if (isNotEmpty)
                buf.setLength(buf.length() - 1);
            buf.append("},");
            return parent;
        }
    }

    private static class AbstractNode<T extends AbstractNode<T>> implements Node<T> {

        protected final StringBuilder buf;
        protected boolean isNotEmpty;

        public AbstractNode(StringBuilder buf) {
            this.buf = buf;
            this.isNotEmpty = false;
        }

        @Override
        public T number(String name, int value) {
            isNotEmpty = true;
            buf.append('\"').append(name).append("\":").append(value).append(',');
            return self();
        }

        @Override
        public NotRootNode<T> object(String name) {
            isNotEmpty = true;
            buf.append('\"').append(name).append("\":{");
            return new NotRootNode<>(buf, self());
        }

        @SuppressWarnings("unchecked")
        protected T self() {
            return (T) this;
        }
    }
}

class Scratch {
    public static void main(String[] args) {
        String str = Json.create()
                .number("a", 4)
                .object("b")
                    .number("a", 4)
                    .number("b", 5)
                    .end()
                .number("c", 5)
                .build();
        System.out.println(str);
    }
}