Source code for ants.fileformats.json

# (C) Crown Copyright, Met Office. All rights reserved.
#
# This file is part of ANTS and is released under the BSD 3-Clause license.
# See LICENSE.txt in the root of the repository for full licensing details.
import json

import numpy as np


[docs] class JSONLoader(object): """JSON loader"""
[docs] def __init__(self, keys=None, dtypes=None, case_sensitive=False): """ JSON loader that handles validity checks, case handling. Parameters ---------- keys : :obj:`str`, optional The key name(s) to read from the JSON. When not provided, all keys are returned from the file. dtypes : :obj:`str`, optional These dtypes correspond to the return numpy dtype of the values extracted from the json. See :class:`numpy.dtype`. If not provided, values extracted from the json are returned as-is. case_sensitive : :obj:`bool`, optional Determine whether the keys provided should be a case sensitive match with that in the file or not. """ if keys is not None and isinstance(keys, str): keys = [keys] if dtypes is not None and isinstance(dtypes, str): dtypes = [dtypes] if dtypes is not None and keys is None: raise ValueError("dtypes provided but keys not provided.") if dtypes: if len(dtypes) != len(keys): msg = "dtypes length {} not equal to the provided keys " "length {}" raise ValueError(msg.format(len(dtypes), len(keys))) dtypes = [np.dtype(dtype) for dtype in dtypes] self._case_sensitive = bool(case_sensitive) if keys: if len(set(keys)) != len(keys): msg = "Duplicate keys? {}" raise ValueError(msg.format(keys)) if not self._case_sensitive: nkeys = [req.lower() for req in keys] if len(keys) != len(set(nkeys)): msg = "Keys: {} appear to be case sensitive".format(keys) raise ValueError(msg) keys = nkeys self._keys = keys self._dtypes = dtypes
def _check_validity(self, dic): keys = dic.keys() if not self._case_sensitive: keys = [key.lower() for key in keys] if self._keys: mkeys = set(keys) rkeys = set(self._keys) diff = rkeys - mkeys if diff: raise KeyError("Keys: {} missing from file".format(diff)) # Remove keys we weren't requesting. stray_keys = mkeys - rkeys [dic.pop(dd) for dd in stray_keys] if self._dtypes and self._keys: for key, dtype in zip(self._keys, self._dtypes): try: len(dic[key]) dic[key] = np.array(dic[key], dtype) except TypeError: dic[key] = dtype.type(dic[key])
[docs] def load(self, filename): """ Load the provided JSON and return a dictionary. Parameters ---------- filename : str Filepath for the JSON file. Returns ------- : dict Dictionary representing the requested keys from the JSON. """ with open(filename, "r") as fh: dic = json.load(fh) self._check_validity(dic) return dic
[docs] def load(filename, **kwargs): """ JSON loader Parameters ---------- **kwargs : See :class:`JSONLoader` Returns ------- : dict Dictionary representing the requested keys from the JSON. """ jloader = JSONLoader(**kwargs) return jloader.load(filename)