def mapped_jsontree_class(mapping):
    """Return a class which is a jsontree, but with a supplied attribute name
    mapping. The mapping argument can be a mapping object
    (dict, jsontree, etc.) or it can be a callable which takes a single
    argument (the attribute name), and returns a new name.
    
    This is useful in situations where you have a jsontree with keys that are
    not valid python attribute names, to simplify communication with a client
    library, or allow for configurable names.
    
    For example:
    
    >>> numjt = mapped_jsontree_class(dict(one='1', two='2', three='3'))
    >>> number = numjt()
    >>> number.one = 'something'
    >>> number
    defaultdict(<class 'jsontree.mapped_jsontree'>, {'1': 'something'})
    
    This is very useful for abstracting field names that may change between
    a development sandbox and production environment. Both FogBugz and Jira
    bug trackers have custom fields with dynamically generated values. These
    field names can be abstracted out into a configruation mapping, and the
    jsontree code can be standardized.
    
    This can also be iseful for JavaScript API's (PHPCake) which insist on
    having spaces in some key names. A function can be supplied which maps
    all '_'s in the attribute name to spaces:
    
    >>> spacify = lambda name: name.replace('_', ' ')
    >>> spacemapped = mapped_jsontree_class(spacify)
    >>> sm = spacemapped()
    >>> sm.hello_there = 5
    >>> sm.hello_there
    5
    >>> sm.keys()
    ['hello there']
    
        
    This will also work with non-string keys for translating from libraries
    that use object keys in python over to string versions of the keys in JSON
    
    >>> numjt = mapped_jsontree_class(dict(one=1, two=2))
    >>> number = numjt()
    >>> number.one = 'something'
    >>> number
    defaultdict(<class 'jsontree.mapped_jsontree'>, {1: 'something'})
    >>> numjt_as_text = mapped_jsontree_class(dict(one='1', two='2'))
    >>> dumped_number = dumps(number)
    >>> loaded_number = loads(dumped_number, jsontreecls=numjt_as_text)
    >>> loaded_number.one
    'something'
    >>> loaded_number
    defaultdict(<class 'jsontree.mapped_jsontree'>, {'1': 'something'})
    
    """
    mapper = mapping
    if not callable(mapping):
        if not isinstance(mapping, collections.Mapping):
            raise TypeError("Argument mapping is not collable or an instance "
                              "of collections.Mapping")
        mapper = lambda name: mapping.get(name, name)
    class mapped_jsontree(collections.defaultdict):
        def __init__(self, *args, **kwdargs):
            super(mapped_jsontree, self).__init__(mapped_jsontree, *args, **kwdargs)
        def __getattribute__(self, name):
            mapped_name = mapper(name)
            if not isinstance(mapped_name, basestring):
                return self[mapped_name]
            try:
                return object.__getattribute__(self, mapped_name)
            except AttributeError:
                return self[mapped_name]
        def __setattr__(self, name, value):
            mapped_name = mapper(name)
            self[mapped_name] = value
            return value
    return mapped_jsontree