JSON Notes


metadata

There is little in the way of standards for JSON. It lacks all the namespace features of XML. It lacks the ability to serialize Java objects effectively for transport or "marshalling" from one place to another. Some make use of the '@' as a convention to indicate metadata. For instance, the following suggests the JSON describes a Java object.

{
    "@class" : "org.acme.data.Employee",
    "name" : " Bill Findlay",
    "id" : 4096283
}

Or, the metadata reference can be used to hook up a foreign key in a database to another table:

{
    "name" : "Bill Findlay",
    "id" : 4096283
    "address" : "@addrtable",
    "telephone" : "801 555-1212"
}

...whereas addrtable is:

{
    ...
    {
        "id" : 1234567,
        "billing" : "40561 Jack the Ripper Boulevard, Los Angeles, CA 90640",
        "shipping" : "40561 Jack the Ripper Boulevard, Los Angeles, CA 90640",
    },
    {
        "id" : 4096283,
        "billing" : "1313 Mockingbird Lane, Mockingbird Heights, CA 90310",
        "shipping" : "PO Box 666, Lancaster, CA, 94532"
    }
    ...
}

Pretty-printing

Got a string containing a stream of unformatted JSON? Need to turn:

    {"resultCode":0,"resultDescription":"Success","typeName":"iwsUserExistsResult",\
        "hostName":"https:\/\/acme","acctOid":10000132001,"acctType":"FUL"}

into:

{
    "resultCode":0,
    "resultDescription":"Success",
    "typeName":"iwsUserExistsResult",
    "hostName":"https:\/\/acme",
    "acctOid":10000132001,
    "acctType":"FUL"
}

?

    /**
     * This pretty-prints a JSON payload returned from the server. It's pretty dang simple and not
     * much good for super-duper stuff, but what we expect back isn't complex anyway. Vastly improves
     * over having to squint.
     *
     * @param source the returned payload (JSON).
     * @param tabWidth width in spaces of the tab used to display hierarchy.
     * @return string containing the payload interspersed with new lines and spaces for indentation.
     */
    static final String prettyPrint( String source, int tabWidth )
    {
        StringBuffer    sb       = new StringBuffer();
        String          tab      = "    ";
        int             len      = source.length();
        int             level    = 0;           // magnitude of hierarchy
        boolean         inString = false;       // don't do hierarchy while between quotes!

        if( tabWidth != 4 )
        {
            StringBuffer t = new StringBuffer();

            for( int tw = 0; tw < tabWidth; tw++ )
                t.append( ' ' );

            tab = t.toString();
        }

        for( int index = 0 ; index < len; index++ )
        {
            char    ch = source.charAt( index );

            switch( ch )
            {
                case '\n' :
                    break;
                case '"' :
                    if( inString )
                        inString = false;
                    else
                        inString = true;
                    sb.append( ch );
                    break;
                case '{' : case '[' :
                    if( inString )
                    {
                        sb.append( ch );
                        break;
                    }

                    level++;
                    sb.append( ch );
                    sb.append( '\n' );
                    for( int l = 0; l < level; l++ )
                        sb.append( tab );
                    break;
                case '}' : case ']' :
                    if( inString )
                    {
                        sb.append( ch );
                        break;
                    }

                    level--;
                    sb.append( '\n' );
                    for( int l = 0; l < level; l++ )
                        sb.append( tab );
                    sb.append( ch );
                    break;
                case ',' :
                    if( inString )
                    {
                        sb.append( ch );
                        break;
                    }

                    sb.append( ",\n" );
                    for( int l = 0; l < level; l++ )
                        sb.append( tab );
                    break;
                default :
                    sb.append( ch );
                    break;
            }
        }

        return sb.toString();
    }