# Allen Institute Software License - This software license is the 2-clause BSD
# license plus a third clause that prohibits redistribution for commercial
# purposes without further permission.
#
# Copyright 2015-2016. Allen Institute. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Redistributions for commercial purposes are not permitted without the
# Allen Institute's written permission.
# For purposes of this license, commercial purposes is the incorporation of the
# Allen Institute's software into anything for which you will charge fees or
# other compensation. Contact terms@alleninstitute.org for commercial licensing
# opportunities.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
import numpy as np
import simplejson as json
import math
import re
import logging
ju_logger = logging.getLogger(__name__)
try:
import urllib.request as urllib_request
except ImportError:
import urllib2 as urllib_request
try:
from urllib.parse import urlparse
except ImportError:
import urlparse
[docs]def read(file_name):
""" Shortcut reading JSON from a file. """
with open(file_name, 'rb') as f:
json_string = f.read().decode('utf-8')
if len(json_string)==0: # If empty file
json_string='{}' # Create a string that will give an empty JSON object instead of an error
json_obj = json.loads(json_string)
return json_obj
[docs]def write(file_name, obj):
""" Shortcut for writing JSON to a file. This also takes care of serializing numpy and data types. """
with open(file_name, 'wb') as f:
try:
f.write(write_string(obj)) # Python 2.7
except TypeError:
f.write(bytes(write_string(obj), 'utf-8')) # Python 3
[docs]def write_string(obj):
""" Shortcut for writing JSON to a string. This also takes care of serializing numpy and data types. """
return json.dumps(obj,
indent=2,
ignore_nan=True,
default=json_handler,
iterable_as_array=True)
[docs]def read_url(url, method='POST'):
if method == 'GET':
return read_url_get(url)
elif method == 'POST':
return read_url_post(url)
else:
raise Exception('Unknown request method: (%s)' % method)
[docs]def read_url_get(url):
'''Transform a JSON contained in a file into an equivalent
nested python dict.
Parameters
----------
url : string
where to get the json.
Returns
-------
dict
Python version of the input
Note: if the input is a bare array or literal, for example,
the output will be of the corresponding type.
'''
response = urllib_request.urlopen(url)
json_string = response.read().decode('utf-8')
return json.loads(json_string)
[docs]def read_url_post(url):
'''Transform a JSON contained in a file into an equivalent
nested python dict.
Parameters
----------
url : string
where to get the json.
Returns
-------
dict
Python version of the input
Note: if the input is a bare array or literal, for example,
the output will be of the corresponding type.
'''
urlp = urlparse.urlparse(url)
main_url = urlparse.urlunsplit(
(urlp.scheme, urlp.netloc, urlp.path, '', ''))
data = json.dumps(dict(urlparse.parse_qsl(urlp.query)))
handler = urllib_request.HTTPHandler()
opener = urllib_request.build_opener(handler)
request = urllib_request.Request(main_url, data)
request.add_header("Content-Type", 'application/json')
request.get_method = lambda: 'POST'
try:
response = opener.open(request)
except Exception as e:
response = e
if response.code == 200:
json_string = response.read()
else:
json_string = response.read()
return json.loads(json_string)
[docs]def json_handler(obj):
""" Used by write_json convert a few non-standard types to things that the json package can handle. """
if hasattr(obj, 'to_dict'):
return obj.to_dict()
elif isinstance(obj, np.ndarray):
return obj.tolist()
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.integer):
return int(obj)
elif (isinstance(obj, np.bool) or
isinstance(obj, np.bool_)):
return bool(obj)
elif hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
raise TypeError(
'Object of type %s with value of %s is not JSON serializable' %
(type(obj), repr(obj)))