It's unclear just how much help you need with json
encoding/decoding, or with working with numpy
. For example, how did you create the complex array in the first place?
What your encoding has done is render the array as a list of lists. The decoder than has to convert that back to an array of the appropriate dtype. For example:
d = json.loads(encoded)
a = np.dot(d['some_key'],np.array([1,1j]))
# array([ 1.+1.j, 2.+5.j, 3.-4.j])
This isn't the only way to create such an array from this list, and it probably fails with more general shapes, but it's a start.
The next task is figuring out when to use such a routine. If you know you are going to receive such an array, then just do this decoding.
Another option is to add one or more keys to the dictionary that mark this variable as a complex nparray. One key might also encode its shape (though that is also deducible from the nesting of the list of lists).
Does this point in the right direction? Or do you need further help with each step?
One of the answers to this 'SimpleJSON and NumPy array' question
https://stackoverflow.com/a/24375113/901925
handles both the encoding and decoding of numpy
arrays. It encodes a dictionary with the dtype and shape, and the array's data buffer. So the JSON
string does not mean much to a human. But does handle general arrays, including ones with complex dtype.
expected
and dump
prints are:
[ 1.+1.j 2.+5.j 3.-4.j]
{"dtype": "complex128", "shape": [3],
"__ndarray__": "AAAAAAAA8D8AAAAAAADwPwAAAAAAAABAAAAAAAAAFEAAAAAAAAAIQAAAAAAAABDA"}
The custom decoding is done with an object_hook
function, which takes a dict
and returns an array (if possible).
json.loads(dumped, object_hook=json_numpy_obj_hook)
Following that model, here's a crude hook
that would transform every JSON array into a np.array
, and every one with 2 columns into a 1d complex array:
def numpy_hook(dct):
jj = np.array([1,1j])
for k,v in dct.items():
if isinstance(v, list):
v = np.array(v)
if v.ndim==2 and v.shape[1]==2:
v = np.dot(v,jj)
dct[k] = v
return dct
It would be better, I think, to encode some dictionary key to flag a numpy array
, and another to flag a complex
dtype.
I can improve the hook to handle regular lists, and other array dimensions:
def numpy_hook(dct):
jj = np.array([1,1j])
for k,v in dct.items():
if isinstance(v, list):
# try to turn list into numpy array
v = np.array(v)
if v.dtype==object:
# not a normal array, don't change it
continue
if v.ndim>1 and v.shape[-1]==2:
# guess it is a complex array
# this information should be more explicit
v = np.dot(v,jj)
dct[k] = v
return dct
It handles this structure:
A = np.array([1+1j,2+5j, 3-4j])
B = np.arange(12).reshape(3,4)
C = A+B.T
test = {'id': 'stream id',
'arrays': [{'A': A}, {'B': B}, {'C': C}]}
returning:
{u'arrays': [{u'A': array([ 1.+1.j, 2.+5.j, 3.-4.j])},
{u'B': array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])},
{u'C': array([[ 1.+1.j, 6.+5.j, 11.-4.j],
[ 2.+1.j, 7.+5.j, 12.-4.j],
[ 3.+1.j, 8.+5.j, 13.-4.j],
[ 4.+1.j, 9.+5.j, 14.-4.j]])}],
u'id': u'stream id'}
Any more generality requires, I think, modifications to the encoding to make the array identity explicit.