Repository: keras-team/keras

Issue:
TypeError: Not JSON Serializable
There is a sample code that will reproduce the error:
https://gist.github.com/henry0312/c5e37cf219498a692520ddc01d2e41ba

Run: `python keras_save_json_bug.py`

```
Traceback (most recent call last):
  File "keras_save_json_bug.py", line 59, in <module>
    json_string = net.to_json()
  File "/usr/local/var/pyenv/versions/3.5.1/lib/python3.5/site-packages/keras/engine/topology.py", line 2373, in to_json
    return json.dumps(model_config, default=get_json_type, **kwargs)
  File "/usr/local/var/pyenv/versions/3.5.1/lib/python3.5/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/local/var/pyenv/versions/3.5.1/lib/python3.5/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/var/pyenv/versions/3.5.1/lib/python3.5/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/var/pyenv/versions/3.5.1/lib/python3.5/site-packages/keras/engine/topology.py", line 2366, in get_json_type
    raise TypeError('Not JSON Serializable')
TypeError: Not JSON Serializable
```



Discussion:
What is your environment? I use Keras 1.0.3 with both tensorflow / theano backend and no error was produced with your code.

My environment:
- OS: OS X 10.11.5 and Ubuntu 14.04.4
- Python: 3.5.1
- numpy: 1.11.0
- scipy: 0.17.1
- Theano: 0.8.2
- Keras: 1.0.3

The serialization works fine... in Python 2. 

> The serialization works fine... in Python 2. 

oh... I also confirmed the sample code worked fine in Python 2 😞
There are something wrong with Python 3.

I think the issue is related to https://github.com/fchollet/keras/issues/2582, but `to_yaml` works fine in Python 3.

And I found that the below changed sample (i.e. not using lambda) worked fine in Python 3.

``` python
# before
merged_vector = merge([y1, y2], mode=lambda x: x[0] - x[1], output_shape=(None, 64))
# after
merged_vector = merge([y1, y2], mode='sum', output_shape=(None, 64))
```

this code raises the same error:

``` python
import json
import marshal

func = lambda x, y: x + y
dump = marshal.dumps(func.__code__)
json.dumps({'test': dump})
```

so I think there are something wrong around https://github.com/fchollet/keras/blob/master/keras/engine/topology.py#L1330


Resolving patch:
diff --git a/keras/engine/topology.py b/keras/engine/topology.py
--- a/keras/engine/topology.py
+++ b/keras/engine/topology.py
@@ -1327,9 +1327,9 @@ def get_config(self):
 
         if isinstance(self.mode, python_types.LambdaType):
             if py3:
-                mode = marshal.dumps(self.mode.__code__)
+                mode = marshal.dumps(self.mode.__code__).decode('raw_unicode_escape')
             else:
-                mode = marshal.dumps(self.mode.func_code)
+                mode = marshal.dumps(self.mode.func_code).decode('raw_unicode_escape')
             mode_type = 'lambda'
         elif callable(self.mode):
             mode = self.mode.__name__
@@ -1365,7 +1365,7 @@ def from_config(cls, config):
         if mode_type == 'function':
             mode = globals()[config['mode']]
         elif mode_type == 'lambda':
-            mode = marshal.loads(config['mode'])
+            mode = marshal.loads(config['mode'].encode('raw_unicode_escape'))
             mode = python_types.FunctionType(mode, globals())
         else:
             mode = config['mode']


Test patch: