def to_python(self, value):
        """
        This assumes the value has been preprocessed into a dictionary of the form:
        {'type': <geometry_type>, 'geometry': <raw_geometry>}
        """

        if not value or isinstance(value, BaseGeometry):
            return value

        geometry_type = value['type']
        geometry = value['geometry']

        try:
            if geometry_type == 'esriGeometryPoint':
                if 'x' in geometry:
                    data = json.loads(geometry)
                    x, y = data['x'], data['y']
                else:
                    x, y = [float(val) for val in geometry.split(',')]
                return Point(x, y)

            elif geometry_type == 'esriGeometryMultipoint':
                data = json.loads(geometry)
                return MultiPoint([(p['0'], p['1']) for p in data['points']])

            elif geometry_type == 'esriGeometryPolyline':
                data = json.loads(geometry)
                return MultiLineString([((l[0][0], l[0][1]), (l[1][0], l[1][1])) for l in data['paths']])

            elif geometry_type == 'esriGeometryPolygon':
                data = json.loads(geometry)
                rings = [LinearRing([(p[0], p[1]) for p in r]) for r in data['rings']]
                return Polygon([r for r in rings if not r.is_ccw], interiors=[r for r in rings if r.is_ccw])

            elif geometry_type == 'esriGeometryEnvelope':
                if 'xmin' in geometry:
                    data = json.loads(geometry)
                    xmin, ymin, xmax, ymax = [data[k] for k in ('xmin', 'ymin', 'xmax', 'ymax')]
                else:
                    xmin, ymin, xmax, ymax = [float(val) for val in geometry.split(',')]
                return MultiPoint([(xmin, ymin), (xmax, ymax)]).envelope

            else:
                raise ValueError
        except ValueError:
            raise ValidationError('Invalid geometry')