'Serialize this group as JSON
@param fields: the columns to include for each item
@param labels: columns labels as dict {key: label},
including the labels for grouping axes
@param represent: dict of representation methods for grouping
axis values {colname: function}
@param as_dict: return output as dict rather than JSON string
@param master: this is the top-level group (internal)
JSON Format:
{"c": [key, ...],          ....... list of keys for visible columns
"g": [key, ...],          ....... list of keys for grouping axes
"l": [(key, label), ...], ....... list of key-label pairs
"k": key,                 ....... grouping key for subgroups
"d": [                    ....... list of sub-groups
{"v": string,         ....... the grouping value for this subgroup (represented)
"k": key             ....... the grouping key for subgroups
"d": [...]           ....... list of subgroups (nested)
"i": [               ....... list of items in this group
{key: value,    ....... key-value pairs for visible columns
"t": {               ....... list of group totals
key: value,      ....... key-value pairs for totals
"i": [...],                ....... list of items (if no grouping)
"t": [...],                ....... list of grand totals
"e": boolean               ....... empty-flag'

def json(self, fields=None, labels=None, represent=None, as_dict=False, master=True):

    T = current.T
    output = {}
    if (not fields):
        raise SyntaxError
    if master:
        if (labels is None):
            labels = {}
        def check_label(colname):
            if (colname in labels):
                label = (labels[colname] or '')
            else:
                fname = colname.split('.', 1)[(-1)]
                label = '    '.join([s.strip().capitalize() for s in fname.split('_') if s])
                label = labels[colname] = T(label)
            return str(label)
        grouping = []
        groupby = self.groupby
        if groupby:
            for axis in groupby:
                check_label(axis)
                grouping.append(axis)
        output['g'] = grouping
        columns = []
        for colname in fields:
            check_label(colname)
            columns.append(colname)
        output['c'] = columns
        output['l'] = dict(((c, str(l)) for (c, l) in labels.items()))
    key = self.key
    if key:
        output['k'] = key
        representations = None
        renderer = (represent.get(key) if represent else None)
        if (renderer and hasattr(renderer, 'bulk')):
            values = [group[key] for group in self.groups]
            representations = renderer.bulk(values)
        data = []
        add_group = data.append
        for group in self.groups:
            gdict = group.json(fields, labels, represent=represent, as_dict=True, master=False)
            value = group[key]
            if (representations is not None):
                value = representations.get(value)
            elif (renderer is not None):
                value = renderer(value)
            value = s3_unicode(value).encode('utf-8')
            gdict['v'] = value
            add_group(gdict)
        if master:
            output['e'] = (len(data) == 0)
        output['d'] = data
        output['i'] = None
    else:
        oitems = []
        add_item = oitems.append
        for item in self.items:
            oitem = {}
            for colname in fields:
                if (colname in item):
                    value = (item[colname] or '')
                else:
                    raw = item.get('_row')
                    try:
                        value = raw.get(colname)
                    except (AttributeError, TypeError):
                        value = None
                if (value is None):
                    value = ''
                else:
                    value = s3_unicode(value).encode('utf-8')
                oitem[colname] = value
            add_item(oitem)
        if master:
            output['e'] = (len(oitems) == 0)
        output['d'] = None
        output['i'] = oitems
    aggregates = self._aggregates
    totals = {}
    for (k, a) in aggregates.items():
        (method, colname) = k
        totals[colname] = s3_unicode(a.result).encode('utf-8')
    output['t'] = totals
    if (master and (not as_dict)):
        output = json.dumps(output, separators=SEPARATORS)
    return output
