class SignUtils {

    static String asCanonicalString(Object obj) {
        StringBuilder strBuffer = new StringBuilder();
        if (obj instanceof Struct) {
            Struct struct = (Struct) obj;
            strBuffer.append('{');
            for (String name : struct.sortedNames()) {
                appendSeparator(strBuffer);
                strBuffer.append('"');
                strBuffer.append(name);
                strBuffer.append("\":");
                strBuffer.append(asCanonicalString(struct.get(name)));
            }
            strBuffer.append('}');
        } else if (obj instanceof Array) {
            strBuffer.append('[');
            for (Object item : (Array) obj) {
                appendSeparator(strBuffer);
                strBuffer.append(asCanonicalString(item));
            }
            strBuffer.append(']');
        } else if (obj instanceof String) {
            strBuffer.append('"');
            strBuffer.append(obj);
            strBuffer.append('"');
        } else if (obj instanceof Integer) {
            strBuffer.append(obj);
        } else if (obj instanceof Long) {
            strBuffer.append(obj);
        } else if (obj instanceof Boolean) {
            strBuffer.append(obj);
        } else {
            strBuffer.append(obj.toString());
        }
        return strBuffer.toString();
    }

}