Skip to content

Commit b6427f6

Browse files
authored
Merge pull request #28 from kenblu24/patch-no-jsondefault-hack
Stop monkey-patching custom JSONEncoder.default on json export
2 parents efc2498 + b2d8cc9 commit b6427f6

File tree

1 file changed

+33
-31
lines changed

1 file changed

+33
-31
lines changed

src/superneuromat/neuromorphicmodel.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,33 @@ def clear_memos(self):
24982498
del self.memoized
24992499
self.memoized = {}
25002500

2501+
@staticmethod
2502+
def is_numeric_array(o):
2503+
is_np = isinstance(o, np.ndarray) and o.dtype.kind in 'iuf'
2504+
is_py = isinstance(o, (tuple, list)) and all([isinstance(x, (int, float, bool)) for x in o])
2505+
return is_np or is_py
2506+
2507+
@staticmethod
2508+
def is_bool_array(o):
2509+
if isinstance(o, np.ndarray):
2510+
try:
2511+
return np.issubdtype(o.dtype, np.bool)
2512+
except AttributeError:
2513+
return issubclass(o.dtype.type, np.bool_)
2514+
else:
2515+
return all([isinstance(x, bool) for x in o])
2516+
2517+
@classmethod
2518+
def _json_default(cls, o):
2519+
if isinstance(o, np.ndarray):
2520+
if cls.is_bool_array(o):
2521+
return o.astype(np.int_).tolist()
2522+
return o.tolist()
2523+
if issubclass(o, np.generic):
2524+
return o.__name__
2525+
msg = f'Object of type {o.__class__.__name__} is not JSON serializable'
2526+
raise TypeError(msg)
2527+
25012528
def _to_json_dict(self, array_representation="json-native",
25022529
skipkeys: list[str] | tuple[str] | set[str] | None = None,
25032530
net_name=None, extra=None):
@@ -2530,30 +2557,6 @@ def _to_json_dict(self, array_representation="json-native",
25302557
varnames = set(self.eqvars) - skipkeys
25312558
arep = array_representation
25322559

2533-
def is_numeric_array(o):
2534-
is_np = isinstance(o, np.ndarray) and o.dtype.kind in 'iuf'
2535-
is_py = isinstance(o, (tuple, list)) and all([isinstance(x, (int, float, bool)) for x in o])
2536-
return is_np or is_py
2537-
2538-
def is_bool_array(o):
2539-
if isinstance(o, np.ndarray):
2540-
try:
2541-
return np.issubdtype(o.dtype, np.bool)
2542-
except AttributeError:
2543-
return issubclass(o.dtype.type, np.bool_)
2544-
else:
2545-
return all([isinstance(x, bool) for x in o])
2546-
2547-
def default(self, o):
2548-
if isinstance(o, np.ndarray):
2549-
if is_bool_array(o):
2550-
return o.astype(np.int_).tolist()
2551-
return o.tolist()
2552-
if issubclass(o, np.generic):
2553-
return o.__name__
2554-
msg = f'Object of type {o.__class__.__name__} is not JSON serializable'
2555-
raise TypeError(msg)
2556-
25572560
def get_dtype(o):
25582561
byteorder = o.dtype.byteorder
25592562
if byteorder == '=':
@@ -2572,15 +2575,15 @@ def get_dtype(o):
25722575
data = {var: getattr(self, var) for var in varnames}
25732576

25742577
for k, v in data.items():
2575-
if is_numeric_array(v) and is_bool_array(v):
2578+
if self.is_numeric_array(v) and self.is_bool_array(v):
25762579
data[k] = np.asarray(v, dtype=np.int_).tolist()
25772580
elif arep in ["base85", "base64"]:
25782581
from base64 import b85encode, b64encode
25792582
encode = b85encode if arep == "base85" else b64encode
25802583
data = {var: getattr(self, var) for var in varnames}
25812584
for k, v in data.items():
2582-
if is_numeric_array(v):
2583-
dtype = self.dbin if is_bool_array(v) else self.dd
2585+
if self.is_numeric_array(v):
2586+
dtype = self.dbin if self.is_bool_array(v) else self.dd
25842587
arr = np.asarray(v, dtype=dtype)
25852588
data[k] = {
25862589
"dtype": get_dtype(arr),
@@ -2590,8 +2593,6 @@ def get_dtype(o):
25902593
else:
25912594
raise ValueError("array_representation must be 'json-native' or 'base85'.")
25922595

2593-
json.JSONEncoder.default = default
2594-
25952596
d = {
25962597
"$schema": "https://ornl.github.io/superneuromat/schema/0.1/snn.json",
25972598
"version": "0.1",
@@ -2654,8 +2655,9 @@ def to_json(self, array_representation="json-native",
26542655
>>> snn.to_json(net_name="My SNN", indent=None)
26552656
{"$schema": "https://ornl.github.io/superneuromat/schema/0.1/snn.json", "version": "0.1", "networks": [{"meta": {"array_representation": "json-native", "from": {"module": "superneuromat", "version": "3.1.0"}, "format": "snm", "format_version": "0.1", "type": "SNN"}, "data": {"neuron_refractory_periods": [0, 0], "neuron_states": [0.0, 0.0], "num_synapses": 2, "post_synaptic_neuron_ids": [1, 0], "aneg": [], "enable_stdp": [0, 0], "pre_synaptic_neuron_ids": [0, 1], "neuron_thresholds": [3.141592653589793115997963468544185161590576171875, 0.0], "neuron_refractory_periods_state": [0.0, 0.0], "neuron_reset_states": [0.0, 0.0], "stdp_positive_update": true, "input_spikes": {"3": {"nids": [1], "values": [1.0]}}, "synaptic_delays": [1, 1], "allow_signed_leak": false, "num_neurons": 2, "_sparse": "auto", "_backend": "auto", "apos": [], "manual_setup": false, "spike_train": [[1, 0], [0, 1], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], "neuron_leaks": [Infinity, Infinity], "allow_incorrect_stdp_sign": false, "stdp": true, "synaptic_weights": [1.0, 1.0], "default_dtype": "float64", "stdp_negative_update": true}}]}
26562657
""" # noqa: E501 (line length)
2658+
26572659
d = self._to_json_dict(array_representation, skipkeys=skipkeys, net_name=net_name, extra=extra)
2658-
return json.dumps(d, indent=indent, **kwargs)
2660+
return json.dumps(d, indent=indent, default=self._json_default, **kwargs)
26592661

26602662
def saveas_json(self, fp,
26612663
array_representation="json-native",
@@ -2691,7 +2693,7 @@ def saveas_json(self, fp,
26912693
>>> snn.saveas_json(f, net_name="My SNN")
26922694
"""
26932695
d = self._to_json_dict(array_representation, skipkeys=skipkeys, net_name=net_name, extra=extra)
2694-
return json.dump(d, fp, indent=indent, **kwargs)
2696+
return json.dump(d, fp, indent=indent, default=self._json_default, **kwargs)
26952697

26962698
def from_json_network(self, net_dict: dict, skipkeys: list[str] | tuple[str] | set[str] | None = None):
26972699
from base64 import b85decode, b64decode

0 commit comments

Comments
 (0)