Retrieve data in JSON.
        JSON is expected to be valid against the schema
        at https://developer.mpds.io/mpds.schema.json

        Args:
            search: (dict) Search query like {"categ_A": "val_A", "categ_B": "val_B"},
                documented at https://developer.mpds.io/#Categories
            phases: (list) Phase IDs, according to the MPDS distinct phases concept
            fields: (dict) Data of interest for C-, S-, and P-entries,
                e.g. for phase diagrams: {'C': ['naxes', 'arity', 'shapes']},
                documented at https://developer.mpds.io/#JSON-schemata

        Returns:
            List of dicts: C-, S-, and P-entries, the format is
            documented at https://developer.mpds.io/#JSON-schemata

def get_data(self, search, phases=None, fields=default_fields):
        """
        Retrieve data in JSON.
        JSON is expected to be valid against the schema
        at https://developer.mpds.io/mpds.schema.json

        Args:
            search: (dict) Search query like {"categ_A": "val_A", "categ_B": "val_B"},
                documented at https://developer.mpds.io/#Categories
            phases: (list) Phase IDs, according to the MPDS distinct phases concept
            fields: (dict) Data of interest for C-, S-, and P-entries,
                e.g. for phase diagrams: {'C': ['naxes', 'arity', 'shapes']},
                documented at https://developer.mpds.io/#JSON-schemata

        Returns:
            List of dicts: C-, S-, and P-entries, the format is
            documented at https://developer.mpds.io/#JSON-schemata
        """
        output = []
        fields = {
            key: [jmespath.compile(item) if isinstance(item, str) else item() for item in value]
            for key, value in fields.items()
        } if fields else None

        tot_count = 0

        phases = list(set(phases)) if phases else []

        if len(phases) > self.maxnphases:
            all_phases = array_split(phases, int(math.ceil(
                len(phases)/self.maxnphases
            )))
        else: all_phases = [phases]

        nsteps = len(all_phases)

        for step, current_phases in enumerate(all_phases, start=1):

            counter, hits_count = 0, 0

            while True:
                result = self._request(search, phases=list(current_phases), page=counter)
                if result['error']:
                    raise APIError(result['error'], result.get('code', 0))

                if result['npages'] > self.maxnpages:
                    raise APIError(
                        "Too many hits (%s > %s), please, be more specific" % \
                        (result['count'], self.maxnpages * self.pagesize),
                        2
                    )
                output.extend(self._massage(result['out'], fields))

                if hits_count and hits_count != result['count']:
                    raise APIError("API error: hits count has been changed during the query")

                hits_count = result['count']

                time.sleep(self.chillouttime)

                if counter == result['npages'] - 1:
                    break

                counter += 1

                if self.verbose:
                    sys.stdout.write("\r\t%d%% of step %s from %s" % (
                        (counter/result['npages']) * 100, step, nsteps)
                                    )
                    sys.stdout.flush()

            tot_count += hits_count

        if len(output) != tot_count:
            raise APIError("API error: collected and declared counts of hits differ")

        if self.verbose:
            sys.stdout.write("Got %s hits\r\n" % tot_count)
            sys.stdout.flush()

        return output