8
\$\begingroup\$

I am using the JSON output of the MediaWiki API documented here and here, and I have found that for Boolean values, it often returns an empty string if true and omits it if false. Thus, I want to "rationalize" the response.

(Historical context: This was before a new output format was added that uses native JSON true and false.)

My current code to do so (written some months ago) is located in a giant anonymous function:

user = query.users[0];
invalid = typeof user.invalid != "undefined";
missing = typeof user.missing != "undefined";
groups = (typeof user.groups == "object") ? user.groups : [];
editcount = (typeof user.editcount == "number") ? user.editcount : null;
registration = (typeof user.registration == "string") ?
    UserinfoJsParseDate(user.registration) : null;
blocked = typeof user.blockedby != "undefined";
gender = (typeof user.gender == "string") ? user.gender : null;
lastEdited = (typeof query.usercontribs[0] == "object") &&
    (typeof query.usercontribs[0].timestamp == "string") ?
    UserinfoJsParseDate(query.usercontribs[0].timestamp) : null;

I am trying to clean this up, breaking the script's main components into separate functions:

/**
 * Extract relevant information from the server's response.
 * @param data The server's response to the AJAX request
 * @return An object containing the user's information
 */
function processResponse( data ) {
    var query = data.query, info = {};

    if ( query && query.users && query.users[0] ) {
        var user = query.users[0];

        info.invalid = 'invalid' in user;
        info.missing = 'missing' in user;
        info.groups = user.groups || [];
        info.editcount = ( 'editcount' in user ) ? user.editcount : null;
        info.registration = ( 'registration' in user ) ? parseDate( user.registration ) : null;
        info.blocked = 'blockexpiry' in user;
        info.gender = ( 'gender' in user && user.gender != 'unknown' ) ? user.gender : null;

        info.lastEdited = null;
        if ( query.usercontribs && query.usercontribs[0] ) {
            var contribs = query.usercontribs[0];
            if ( contribs.timestamp ) {
                user.lastEdited = parseDate( contribs.timestamp );
            }
        }

    }

    return info;
}

Is this better, or have I just written more messy code?

\$\endgroup\$
5
\$\begingroup\$

It is certainly better. You can improve it further:

  1. Use early exits to reduce arrow code.
  2. Use a JSON initializer for the result.
  3. Prefix boolean names with 'is'.
  4. Fix the 'user.lastEdited' bug.

.

function processResponse(data) {
    if (!data.query || !data.query.users || !data.query.users[0]) return {};

    var user = data.query.users[0];

    return {
        isInvalid: 'invalid' in user,
        isMissing: 'missing' in user,
        groups: user.groups || [],
        editCount: ('editcount' in user) ? user.editcount : null,
        registration: ('registration' in user) ? parseDate(user.registration) : null,
        isBlocked: 'blockexpiry' in user,
        gender: ('gender' in user && user.gender != 'unknown') ? user.gender : null,
        lastEdited: (data.query.usercontrib
                             && data.query.usercontribs[0] 
                             && data.query.usercontribs[0].timestamp)
                        ? parseDate(data.query.usercontribs[0].timestamp) : null
    };
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.