'Export a resource as JSON
@param resource: the resource to export from
@param start: index of the first record to export
@param limit: maximum number of records to export
@param fields: list of field selectors for fields to include in
the export (None for all fields)
@param orderby: ORDERBY expression
@param represent: whether values should be represented
@param tooltip: additional tooltip field, either a field selector
or an expression "f(k,v)" where f is a function
name that can be looked up from s3db, and k,v are
field selectors for the row, f will be called with
a list of tuples (k,v) for each row and is expected
to return a dict {k:tooltip} => used by
filterOptionsS3 to extract onhover-tooltips for
Ajax-update of options'

def json(self, resource, start=None, limit=None, fields=None, orderby=None, represent=False, tooltip=None):

    if (fields is None):
        fields = resource.list_fields('json_fields', id_column=0)
    if (orderby is None):
        orderby = resource.get_config('orderby', None)
    tooltip_function = None
    if tooltip:
        if (type(tooltip) is list):
            tooltip = tooltip[(-1)]
        import re
        match = re.match('(\\w+)\\((\\w+),(\\w+)\\)', tooltip)
        if match:
            (function_name, kname, vname) = match.groups()
            tooltip_function = current.s3db.get(function_name)
            if tooltip_function:
                if (kname not in fields):
                    fields.append(kname)
                if (vname not in fields):
                    fields.append(vname)
        elif (tooltip not in fields):
            fields.append(tooltip)
    _rows = resource.select(fields, start=start, limit=limit, orderby=orderby, represent=represent).rows
    tn = ('%s.' % resource.tablename)
    rows = []
    rappend = rows.append
    for _row in _rows:
        row = {}
        for f in _row:
            v = _row[f]
            if (tn in f):
                f = f.split(tn, 1)[1]
            row[f] = v
        rappend(row)
    if tooltip:
        if tooltip_function:
            try:
                krfield = resource.resolve_selector(kname)
                vrfield = resource.resolve_selector(vname)
            except (AttributeError, SyntaxError):
                import sys
                current.log.error(sys.exc_info()[1])
            else:
                options = []
                items = {}
                for row in rows:
                    try:
                        k = krfield.extract(row)
                    except KeyError:
                        break
                    try:
                        v = vrfield.extract(row)
                    except KeyError:
                        break
                    items[k] = row
                    options.append((k, v))
                try:
                    tooltips = tooltip_function(options)
                except:
                    import sys
                    current.log.error(sys.exc_info()[1])
                else:
                    if isinstance(tooltips, dict):
                        from s3utils import s3_unicode
                        for (k, v) in tooltips.items():
                            if (k in items):
                                items[k]['_tooltip'] = s3_unicode(v)
        else:
            try:
                tooltip_rfield = resource.resolve_selector(tooltip)
            except (AttributeError, SyntaxError):
                import sys
                current.log.error(sys.exc_info()[1])
            else:
                from s3utils import s3_unicode
                for row in rows:
                    try:
                        value = tooltip_rfield.extract(row)
                    except KeyError:
                        break
                    if value:
                        row['_tooltip'] = s3_unicode(value)
    response = current.response
    if response:
        response.headers['Content-Type'] = 'application/json'
    from gluon.serializers import json as jsons
    return jsons(rows)
