Repository: mars-project/mars

Issue:
Support serializing numpy scalars for mars serialize
<!--
Thank you for your contribution!

Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
-->

**Is your feature request related to a problem? Please describe.**

Mars serialize does not support numpy scalars for now. Support for `complex64` and `complex128` should also be added.

```
In [56]: from mars.serialize import Serializable, ListField                     

In [57]: class Data(Serializable): 
    ...:     f1 = ListField('f1') 
    ...:                                                                        

In [58]: d = Data(f1=[np.int64(0)])                                             

In [59]: d.to_json()                                                            
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-59-21f39261cfa5> in <module>
----> 1 d.to_json()

~/Workspace/mars/mars/serialize/core.pyx in mars.serialize.core.Serializable.to_json()

~/Workspace/mars/mars/serialize/core.pyx in mars.serialize.core.Serializable.serialize()

~/Workspace/mars/mars/serialize/core.pyx in mars.serialize.core.Provider.serialize_model()

~/Workspace/mars/mars/serialize/core.pyx in mars.serialize.core.Field.serialize()

~/Workspace/mars/mars/serialize/core.pyx in mars.serialize.core.Field.serialize()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider.serialize_field()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider._serialize_value()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider._serialize_typed_value()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider._serialize_list()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider._serialize_value()

~/Workspace/mars/mars/serialize/jsonserializer.pyx in mars.serialize.jsonserializer.JsonSerializeProvider._serialize_untyped_value()

TypeError: Unknown type to serialize: <class 'numpy.int64'>
```

**Additional context**

https://github.com/mars-project/mars/issues/476#issuecomment-504872949 brings up the discussion.



Discussion:

Resolving patch:
diff --git a/mars/serialize/protos/value_pb2.py b/mars/serialize/protos/value_pb2.py
--- a/mars/serialize/protos/value_pb2.py
+++ b/mars/serialize/protos/value_pb2.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: mars/serialize/protos/value.proto
 
@@ -19,7 +20,7 @@
   package='',
   syntax='proto3',
   serialized_options=None,
-  serialized_pb=_b('\n!mars/serialize/protos/value.proto\"\xde\x04\n\x05Value\x12\x11\n\x07is_null\x18\x01 \x01(\x08H\x00\x12\x0b\n\x01\x62\x18\x02 \x01(\x08H\x00\x12\x0b\n\x01i\x18\x03 \x01(\x03H\x00\x12\x0b\n\x01\x66\x18\x04 \x01(\x02H\x00\x12\x0b\n\x01s\x18\x05 \x01(\x0cH\x00\x12\x0b\n\x01u\x18\x06 \x01(\tH\x00\x12\x1b\n\x04list\x18\x07 \x01(\x0b\x32\x0b.Value.ListH\x00\x12\x1b\n\x04\x64ict\x18\x08 \x01(\x0b\x32\x0b.Value.DictH\x00\x12\x1d\n\x05slice\x18\t \x01(\x0b\x32\x0c.Value.SliceH\x00\x12\r\n\x03\x61rr\x18\n \x01(\x0cH\x00\x12\x0f\n\x05\x64type\x18\x0b \x01(\x0cH\x00\x12\x19\n\x03key\x18\x0c \x01(\x0b\x32\n.Value.KeyH\x00\x12\x14\n\ndatetime64\x18\r \x01(\x0cH\x00\x12\x15\n\x0btimedelta64\x18\x0e \x01(\x0cH\x00\x12\x0f\n\x05index\x18\x0f \x01(\x0cH\x00\x12\x10\n\x06series\x18\x10 \x01(\x0cH\x00\x12\x13\n\tdataframe\x18\x11 \x01(\x0cH\x00\x1a/\n\x04List\x12\x10\n\x08is_tuple\x18\x01 \x01(\x08\x12\x15\n\x05value\x18\x02 \x03(\x0b\x32\x06.Value\x1an\n\x05Slice\x12\x0f\n\x07is_null\x18\x04 \x01(\x08\x12\x13\n\tstart_val\x18\x01 \x01(\x03H\x00\x12\x12\n\x08stop_val\x18\x02 \x01(\x03H\x01\x12\x12\n\x08step_val\x18\x03 \x01(\x03H\x02\x42\x07\n\x05startB\x06\n\x04stopB\x06\n\x04step\x1a>\n\x04\x44ict\x12\x19\n\x04keys\x18\x01 \x01(\x0b\x32\x0b.Value.List\x12\x1b\n\x06values\x18\x02 \x01(\x0b\x32\x0b.Value.List\x1a\x1e\n\x03Key\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\tB\x07\n\x05valueb\x06proto3')
+  serialized_pb=_b('\n!mars/serialize/protos/value.proto\"\xa2\x05\n\x05Value\x12\x11\n\x07is_null\x18\x01 \x01(\x08H\x00\x12\x0b\n\x01\x62\x18\x02 \x01(\x08H\x00\x12\x0b\n\x01i\x18\x03 \x01(\x03H\x00\x12\x0b\n\x01\x66\x18\x04 \x01(\x01H\x00\x12\x1b\n\x01\x63\x18\x13 \x01(\x0b\x32\x0e.Value.ComplexH\x00\x12\x0b\n\x01s\x18\x05 \x01(\x0cH\x00\x12\x0b\n\x01u\x18\x06 \x01(\tH\x00\x12\x1b\n\x04list\x18\x07 \x01(\x0b\x32\x0b.Value.ListH\x00\x12\x1b\n\x04\x64ict\x18\x08 \x01(\x0b\x32\x0b.Value.DictH\x00\x12\x1d\n\x05slice\x18\t \x01(\x0b\x32\x0c.Value.SliceH\x00\x12\r\n\x03\x61rr\x18\n \x01(\x0cH\x00\x12\x0f\n\x05\x64type\x18\x0b \x01(\x0cH\x00\x12\x19\n\x03key\x18\x0c \x01(\x0b\x32\n.Value.KeyH\x00\x12\x14\n\ndatetime64\x18\r \x01(\x0cH\x00\x12\x15\n\x0btimedelta64\x18\x0e \x01(\x0cH\x00\x12\x0f\n\x05index\x18\x0f \x01(\x0cH\x00\x12\x10\n\x06series\x18\x10 \x01(\x0cH\x00\x12\x13\n\tdataframe\x18\x11 \x01(\x0cH\x00\x1a/\n\x04List\x12\x10\n\x08is_tuple\x18\x01 \x01(\x08\x12\x15\n\x05value\x18\x02 \x03(\x0b\x32\x06.Value\x1an\n\x05Slice\x12\x0f\n\x07is_null\x18\x04 \x01(\x08\x12\x13\n\tstart_val\x18\x01 \x01(\x03H\x00\x12\x12\n\x08stop_val\x18\x02 \x01(\x03H\x01\x12\x12\n\x08step_val\x18\x03 \x01(\x03H\x02\x42\x07\n\x05startB\x06\n\x04stopB\x06\n\x04step\x1a>\n\x04\x44ict\x12\x19\n\x04keys\x18\x01 \x01(\x0b\x32\x0b.Value.List\x12\x1b\n\x06values\x18\x02 \x01(\x0b\x32\x0b.Value.List\x1a%\n\x07\x43omplex\x12\x0c\n\x04real\x18\x01 \x01(\x01\x12\x0c\n\x04imag\x18\x02 \x01(\x01\x1a\x1e\n\x03Key\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\tB\x07\n\x05valueb\x06proto3')
 )
 
 
@@ -58,8 +59,8 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=380,
-  serialized_end=427,
+  serialized_start=409,
+  serialized_end=456,
 )
 
 _VALUE_SLICE = _descriptor.Descriptor(
@@ -118,8 +119,8 @@
       name='step', full_name='Value.Slice.step',
       index=2, containing_type=None, fields=[]),
   ],
-  serialized_start=429,
-  serialized_end=539,
+  serialized_start=458,
+  serialized_end=568,
 )
 
 _VALUE_DICT = _descriptor.Descriptor(
@@ -155,8 +156,45 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=541,
-  serialized_end=603,
+  serialized_start=570,
+  serialized_end=632,
+)
+
+_VALUE_COMPLEX = _descriptor.Descriptor(
+  name='Complex',
+  full_name='Value.Complex',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='real', full_name='Value.Complex.real', index=0,
+      number=1, type=1, cpp_type=5, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='imag', full_name='Value.Complex.imag', index=1,
+      number=2, type=1, cpp_type=5, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=634,
+  serialized_end=671,
 )
 
 _VALUE_KEY = _descriptor.Descriptor(
@@ -192,8 +230,8 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=605,
-  serialized_end=635,
+  serialized_start=673,
+  serialized_end=703,
 )
 
 _VALUE = _descriptor.Descriptor(
@@ -226,97 +264,104 @@
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
       name='f', full_name='Value.f', index=3,
-      number=4, type=2, cpp_type=6, label=1,
+      number=4, type=1, cpp_type=5, label=1,
       has_default_value=False, default_value=float(0),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='s', full_name='Value.s', index=4,
+      name='c', full_name='Value.c', index=4,
+      number=19, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='s', full_name='Value.s', index=5,
       number=5, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='u', full_name='Value.u', index=5,
+      name='u', full_name='Value.u', index=6,
       number=6, type=9, cpp_type=9, label=1,
       has_default_value=False, default_value=_b("").decode('utf-8'),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='list', full_name='Value.list', index=6,
+      name='list', full_name='Value.list', index=7,
       number=7, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='dict', full_name='Value.dict', index=7,
+      name='dict', full_name='Value.dict', index=8,
       number=8, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='slice', full_name='Value.slice', index=8,
+      name='slice', full_name='Value.slice', index=9,
       number=9, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='arr', full_name='Value.arr', index=9,
+      name='arr', full_name='Value.arr', index=10,
       number=10, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='dtype', full_name='Value.dtype', index=10,
+      name='dtype', full_name='Value.dtype', index=11,
       number=11, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='key', full_name='Value.key', index=11,
+      name='key', full_name='Value.key', index=12,
       number=12, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='datetime64', full_name='Value.datetime64', index=12,
+      name='datetime64', full_name='Value.datetime64', index=13,
       number=13, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='timedelta64', full_name='Value.timedelta64', index=13,
+      name='timedelta64', full_name='Value.timedelta64', index=14,
       number=14, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='index', full_name='Value.index', index=14,
+      name='index', full_name='Value.index', index=15,
       number=15, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='series', full_name='Value.series', index=15,
+      name='series', full_name='Value.series', index=16,
       number=16, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='dataframe', full_name='Value.dataframe', index=16,
+      name='dataframe', full_name='Value.dataframe', index=17,
       number=17, type=12, cpp_type=9, label=1,
       has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
@@ -325,7 +370,7 @@
   ],
   extensions=[
   ],
-  nested_types=[_VALUE_LIST, _VALUE_SLICE, _VALUE_DICT, _VALUE_KEY, ],
+  nested_types=[_VALUE_LIST, _VALUE_SLICE, _VALUE_DICT, _VALUE_COMPLEX, _VALUE_KEY, ],
   enum_types=[
   ],
   serialized_options=None,
@@ -338,7 +383,7 @@
       index=0, containing_type=None, fields=[]),
   ],
   serialized_start=38,
-  serialized_end=644,
+  serialized_end=712,
 )
 
 _VALUE_LIST.fields_by_name['value'].message_type = _VALUE
@@ -356,7 +401,9 @@
 _VALUE_DICT.fields_by_name['keys'].message_type = _VALUE_LIST
 _VALUE_DICT.fields_by_name['values'].message_type = _VALUE_LIST
 _VALUE_DICT.containing_type = _VALUE
+_VALUE_COMPLEX.containing_type = _VALUE
 _VALUE_KEY.containing_type = _VALUE
+_VALUE.fields_by_name['c'].message_type = _VALUE_COMPLEX
 _VALUE.fields_by_name['list'].message_type = _VALUE_LIST
 _VALUE.fields_by_name['dict'].message_type = _VALUE_DICT
 _VALUE.fields_by_name['slice'].message_type = _VALUE_SLICE
@@ -373,6 +420,9 @@
 _VALUE.oneofs_by_name['value'].fields.append(
   _VALUE.fields_by_name['f'])
 _VALUE.fields_by_name['f'].containing_oneof = _VALUE.oneofs_by_name['value']
+_VALUE.oneofs_by_name['value'].fields.append(
+  _VALUE.fields_by_name['c'])
+_VALUE.fields_by_name['c'].containing_oneof = _VALUE.oneofs_by_name['value']
 _VALUE.oneofs_by_name['value'].fields.append(
   _VALUE.fields_by_name['s'])
 _VALUE.fields_by_name['s'].containing_oneof = _VALUE.oneofs_by_name['value']
@@ -415,43 +465,51 @@
 DESCRIPTOR.message_types_by_name['Value'] = _VALUE
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), dict(
+Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), {
 
-  List = _reflection.GeneratedProtocolMessageType('List', (_message.Message,), dict(
-    DESCRIPTOR = _VALUE_LIST,
-    __module__ = 'mars.serialize.protos.value_pb2'
+  'List' : _reflection.GeneratedProtocolMessageType('List', (_message.Message,), {
+    'DESCRIPTOR' : _VALUE_LIST,
+    '__module__' : 'mars.serialize.protos.value_pb2'
     # @@protoc_insertion_point(class_scope:Value.List)
-    ))
+    })
   ,
 
-  Slice = _reflection.GeneratedProtocolMessageType('Slice', (_message.Message,), dict(
-    DESCRIPTOR = _VALUE_SLICE,
-    __module__ = 'mars.serialize.protos.value_pb2'
+  'Slice' : _reflection.GeneratedProtocolMessageType('Slice', (_message.Message,), {
+    'DESCRIPTOR' : _VALUE_SLICE,
+    '__module__' : 'mars.serialize.protos.value_pb2'
     # @@protoc_insertion_point(class_scope:Value.Slice)
-    ))
+    })
   ,
 
-  Dict = _reflection.GeneratedProtocolMessageType('Dict', (_message.Message,), dict(
-    DESCRIPTOR = _VALUE_DICT,
-    __module__ = 'mars.serialize.protos.value_pb2'
+  'Dict' : _reflection.GeneratedProtocolMessageType('Dict', (_message.Message,), {
+    'DESCRIPTOR' : _VALUE_DICT,
+    '__module__' : 'mars.serialize.protos.value_pb2'
     # @@protoc_insertion_point(class_scope:Value.Dict)
-    ))
+    })
+  ,
+
+  'Complex' : _reflection.GeneratedProtocolMessageType('Complex', (_message.Message,), {
+    'DESCRIPTOR' : _VALUE_COMPLEX,
+    '__module__' : 'mars.serialize.protos.value_pb2'
+    # @@protoc_insertion_point(class_scope:Value.Complex)
+    })
   ,
 
-  Key = _reflection.GeneratedProtocolMessageType('Key', (_message.Message,), dict(
-    DESCRIPTOR = _VALUE_KEY,
-    __module__ = 'mars.serialize.protos.value_pb2'
+  'Key' : _reflection.GeneratedProtocolMessageType('Key', (_message.Message,), {
+    'DESCRIPTOR' : _VALUE_KEY,
+    '__module__' : 'mars.serialize.protos.value_pb2'
     # @@protoc_insertion_point(class_scope:Value.Key)
-    ))
+    })
   ,
-  DESCRIPTOR = _VALUE,
-  __module__ = 'mars.serialize.protos.value_pb2'
+  'DESCRIPTOR' : _VALUE,
+  '__module__' : 'mars.serialize.protos.value_pb2'
   # @@protoc_insertion_point(class_scope:Value)
-  ))
+  })
 _sym_db.RegisterMessage(Value)
 _sym_db.RegisterMessage(Value.List)
 _sym_db.RegisterMessage(Value.Slice)
 _sym_db.RegisterMessage(Value.Dict)
+_sym_db.RegisterMessage(Value.Complex)
 _sym_db.RegisterMessage(Value.Key)
 
 


Test patch:
diff --git a/mars/serialize/tests/test_serialize.py b/mars/serialize/tests/test_serialize.py
--- a/mars/serialize/tests/test_serialize.py
+++ b/mars/serialize/tests/test_serialize.py
@@ -37,7 +37,8 @@
     UInt32Field, UInt64Field, Float16Field, Float32Field, Float64Field, BoolField, \
     Datetime64Field, Timedelta64Field, DataTypeField, KeyField, ReferenceField, OneOfField, \
     ListField, NDArrayField, DictField, TupleField, ValueType, serializes, deserializes, \
-    IndexField, SeriesField, DataFrameField, SliceField, ProviderType, AttributeAsDict
+    IndexField, SeriesField, DataFrameField, SliceField, Complex64Field, Complex128Field, \
+    AnyField, ProviderType, AttributeAsDict
 from mars.serialize import dataserializer
 from mars.serialize.pbserializer import ProtobufSerializeProvider
 from mars.serialize.jsonserializer import JsonSerializeProvider
@@ -58,6 +59,8 @@ class Node1(Serializable):
     d1 = Float16Field('d1')
     d2 = Float32Field('d2')
     d3 = Float64Field('d3')
+    cl1 = Complex64Field('cl1')
+    cl2 = Complex128Field('cl2')
     e = BoolField('e')
     f = KeyField('f')
     g = ReferenceField('g', 'Node2')
@@ -81,6 +84,10 @@ class Node8(Node1):
     pass
 
 
+class Node9(Node1):
+    f = AnyField('f')
+
+
 class Node2(Base, Serializable):
     a = ListField('a', ValueType.list(ValueType.string))
     _key = StringField('key')
@@ -167,10 +174,12 @@ def testPBSerialize(self):
                       b1=-2, b2=2000, b3=-5000, b4=500000,
                       c1=2, c2=2000, c3=5000, c4=500000,
                       d1=2.5, d2=7.37, d3=5.976321,
+                      cl1=1+2j, cl2=2.5+3.1j,
                       e=False,
                       f=node2,
                       g=Node2(a=[['1', '2'], ['3', '4']]),
-                      h=[[2, 3], node2, True, {1: node2}, np.datetime64('1066-10-13'), np.timedelta64(1, 'D')],
+                      h=[[2, 3], node2, True, {1: node2}, np.datetime64('1066-10-13'),
+                         np.timedelta64(1, 'D'), np.complex64(1+2j), np.complex128(2+3j)],
                       i=[Node8(b1=111), Node8(b1=222)])
         node3 = Node3(value=node1)
 
@@ -196,6 +205,8 @@ def testPBSerialize(self):
         self.assertAlmostEqual(node3.value.d1, d_node3.value.d1, places=2)
         self.assertAlmostEqual(node3.value.d2, d_node3.value.d2, places=4)
         self.assertAlmostEqual(node3.value.d3, d_node3.value.d3)
+        self.assertAlmostEqual(node3.value.cl1, d_node3.value.cl1)
+        self.assertAlmostEqual(node3.value.cl2, d_node3.value.cl2)
         self.assertEqual(node3.value.e, d_node3.value.e)
         self.assertIsNot(node3.value.f, d_node3.value.f)
         self.assertEqual(node3.value.f.a, d_node3.value.f.a)
@@ -205,6 +216,8 @@ def testPBSerialize(self):
         self.assertNotIsInstance(d_node3.value.h[1], six.string_types)
         self.assertIs(d_node3.value.h[1], d_node3.value.f)
         self.assertEqual(node3.value.h[2], True)
+        self.assertAlmostEqual(node3.value.h[6], d_node3.value.h[6])
+        self.assertAlmostEqual(node3.value.h[7], d_node3.value.h[7])
         self.assertEqual([n.b1 for n in node3.value.i], [n.b1 for n in d_node3.value.i])
         self.assertIsInstance(d_node3.value.i[0], Node8)
 
@@ -219,10 +232,12 @@ def testJSONSerialize(self):
                       b1=2, b2=2000, b3=5000, b4=500000,
                       c1=2, c2=2000, c3=5000, c4=500000,
                       d1=2.5, d2=7.37, d3=5.976321,
+                      cl1=1+2j, cl2=2.5+3.1j,
                       e=False,
                       f=node2,
                       g=Node2(a=[['1', '2'], ['3', '4']]),
-                      h=[[2, 3], node2, True, {1: node2}, np.datetime64('1066-10-13'), np.timedelta64(1, 'D')],
+                      h=[[2, 3], node2, True, {1: node2}, np.datetime64('1066-10-13'),
+                         np.timedelta64(1, 'D'), np.complex64(1+2j), np.complex128(2+3j)],
                       i=[Node8(b1=111), Node8(b1=222)])
         node3 = Node3(value=node1)
 
@@ -249,6 +264,8 @@ def testJSONSerialize(self):
         self.assertAlmostEqual(node3.value.d1, d_node3.value.d1, places=2)
         self.assertAlmostEqual(node3.value.d2, d_node3.value.d2, places=4)
         self.assertAlmostEqual(node3.value.d3, d_node3.value.d3)
+        self.assertAlmostEqual(node3.value.cl1, d_node3.value.cl1)
+        self.assertAlmostEqual(node3.value.cl2, d_node3.value.cl2)
         self.assertEqual(node3.value.e, d_node3.value.e)
         self.assertIsNot(node3.value.f, d_node3.value.f)
         self.assertEqual(node3.value.f.a, d_node3.value.f.a)
@@ -258,12 +275,64 @@ def testJSONSerialize(self):
         self.assertNotIsInstance(d_node3.value.h[1], six.string_types)
         self.assertIs(d_node3.value.h[1], d_node3.value.f)
         self.assertEqual(node3.value.h[2], True)
+        self.assertAlmostEqual(node3.value.h[6], d_node3.value.h[6])
+        self.assertAlmostEqual(node3.value.h[7], d_node3.value.h[7])
         self.assertEqual([n.b1 for n in node3.value.i], [n.b1 for n in d_node3.value.i])
         self.assertIsInstance(d_node3.value.i[0], Node8)
 
         with self.assertRaises(ValueError):
             serializes(provider, [Node3(value='sth else')])
 
+    def testNumpyDtypePBSerialize(self):
+        provider = ProtobufSerializeProvider()
+
+        node9 = Node9(b1=np.int8(-2), b2=np.int16(2000), b3=np.int32(-5000), b4=np.int64(500000),
+                      c1=np.uint8(2), c2=np.uint16(2000), c3=np.uint32(5000), c4=np.uint64(500000),
+                      d1=np.float16(2.5), d2=np.float32(7.37), d3=np.float64(5.976321),
+                      f=np.int8(3))
+
+        serials = serializes(provider, [node9])
+        d_node9, = deserializes(provider, [Node9], serials)
+
+        self.assertIsNot(node9, d_node9)
+        self.assertEqual(node9.b1, d_node9.b1)
+        self.assertEqual(node9.b2, d_node9.b2)
+        self.assertEqual(node9.b3, d_node9.b3)
+        self.assertEqual(node9.b4, d_node9.b4)
+        self.assertEqual(node9.c1, d_node9.c1)
+        self.assertEqual(node9.c2, d_node9.c2)
+        self.assertEqual(node9.c3, d_node9.c3)
+        self.assertEqual(node9.c4, d_node9.c4)
+        self.assertAlmostEqual(node9.d1, d_node9.d1, places=2)
+        self.assertAlmostEqual(node9.d2, d_node9.d2, places=4)
+        self.assertAlmostEqual(node9.d3, d_node9.d3)
+        self.assertEqual(node9.f, d_node9.f)
+
+    def testNumpyDtypeJSONSerialize(self):
+        provider = JsonSerializeProvider()
+
+        node9 = Node9(b1=np.int8(-2), b2=np.int16(2000), b3=np.int32(-5000), b4=np.int64(500000),
+                      c1=np.uint8(2), c2=np.uint16(2000), c3=np.uint32(5000), c4=np.uint64(500000),
+                      d1=np.float16(2.5), d2=np.float32(7.37), d3=np.float64(5.976321),
+                      f=np.int8(3))
+
+        serials = serializes(provider, [node9])
+        d_node9, = deserializes(provider, [Node9], serials)
+
+        self.assertIsNot(node9, d_node9)
+        self.assertEqual(node9.b1, d_node9.b1)
+        self.assertEqual(node9.b2, d_node9.b2)
+        self.assertEqual(node9.b3, d_node9.b3)
+        self.assertEqual(node9.b4, d_node9.b4)
+        self.assertEqual(node9.c1, d_node9.c1)
+        self.assertEqual(node9.c2, d_node9.c2)
+        self.assertEqual(node9.c3, d_node9.c3)
+        self.assertEqual(node9.c4, d_node9.c4)
+        self.assertAlmostEqual(node9.d1, d_node9.d1, places=2)
+        self.assertAlmostEqual(node9.d2, d_node9.d2, places=4)
+        self.assertAlmostEqual(node9.d3, d_node9.d3)
+        self.assertEqual(node9.f, d_node9.f)
+
     def testAttributeAsDict(self):
         other_data = {}
         if pd:
diff --git a/mars/serialize/tests/testser.proto b/mars/serialize/tests/testser.proto
--- a/mars/serialize/tests/testser.proto
+++ b/mars/serialize/tests/testser.proto
@@ -16,6 +16,8 @@ message Node1Def {
     float d1 = 10;
     float d2 = 11;
     double d3 = 12;
+    Value cl1 = 18;
+    Value cl2 = 19;
     bool e = 13;
     Value f = 14;
     Node2Def g = 15;
diff --git a/mars/serialize/tests/testser_pb2.py b/mars/serialize/tests/testser_pb2.py
--- a/mars/serialize/tests/testser_pb2.py
+++ b/mars/serialize/tests/testser_pb2.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: mars/serialize/tests/testser.proto
 
@@ -20,7 +21,7 @@
   package='',
   syntax='proto3',
   serialized_options=None,
-  serialized_pb=_b('\n\"mars/serialize/tests/testser.proto\x1a!mars/serialize/protos/value.proto\"\xf6\x01\n\x08Node1Def\x12\t\n\x01\x61\x18\x01 \x01(\t\x12\n\n\x02\x62\x31\x18\x02 \x01(\x05\x12\n\n\x02\x62\x32\x18\x03 \x01(\x05\x12\n\n\x02\x62\x33\x18\x04 \x01(\x05\x12\n\n\x02\x62\x34\x18\x05 \x01(\x03\x12\n\n\x02\x63\x31\x18\x06 \x01(\r\x12\n\n\x02\x63\x32\x18\x07 \x01(\r\x12\n\n\x02\x63\x33\x18\x08 \x01(\r\x12\n\n\x02\x63\x34\x18\t \x01(\x04\x12\n\n\x02\x64\x31\x18\n \x01(\x02\x12\n\n\x02\x64\x32\x18\x0b \x01(\x02\x12\n\n\x02\x64\x33\x18\x0c \x01(\x01\x12\t\n\x01\x65\x18\r \x01(\x08\x12\x11\n\x01\x66\x18\x0e \x01(\x0b\x32\x06.Value\x12\x14\n\x01g\x18\x0f \x01(\x0b\x32\t.Node2Def\x12\x11\n\x01h\x18\x10 \x03(\x0b\x32\x06.Value\x12\x14\n\x01i\x18\x11 \x03(\x0b\x32\t.Node1Def\"R\n\x08Node2Def\x12\x11\n\x01\x61\x18\x01 \x01(\x0b\x32\x06.Value\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x03(\x05\x12\n\n\x02id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"E\n\x08Node3Def\x12\x17\n\x02n1\x18\x01 \x01(\x0b\x32\t.Node1DefH\x00\x12\x17\n\x02n2\x18\x02 \x01(\x0b\x32\t.Node2DefH\x00\x42\x07\n\x05value\"b\n\x08Node4Def\x12!\n\x04\x61ttr\x18\x01 \x03(\x0b\x32\x13.Node4Def.AttrEntry\x1a\x33\n\tAttrEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x15\n\x05value\x18\x02 \x01(\x0b\x32\x06.Value:\x02\x38\x01\x62\x06proto3')
+  serialized_pb=_b('\n\"mars/serialize/tests/testser.proto\x1a!mars/serialize/protos/value.proto\"\xa0\x02\n\x08Node1Def\x12\t\n\x01\x61\x18\x01 \x01(\t\x12\n\n\x02\x62\x31\x18\x02 \x01(\x05\x12\n\n\x02\x62\x32\x18\x03 \x01(\x05\x12\n\n\x02\x62\x33\x18\x04 \x01(\x05\x12\n\n\x02\x62\x34\x18\x05 \x01(\x03\x12\n\n\x02\x63\x31\x18\x06 \x01(\r\x12\n\n\x02\x63\x32\x18\x07 \x01(\r\x12\n\n\x02\x63\x33\x18\x08 \x01(\r\x12\n\n\x02\x63\x34\x18\t \x01(\x04\x12\n\n\x02\x64\x31\x18\n \x01(\x02\x12\n\n\x02\x64\x32\x18\x0b \x01(\x02\x12\n\n\x02\x64\x33\x18\x0c \x01(\x01\x12\x13\n\x03\x63l1\x18\x12 \x01(\x0b\x32\x06.Value\x12\x13\n\x03\x63l2\x18\x13 \x01(\x0b\x32\x06.Value\x12\t\n\x01\x65\x18\r \x01(\x08\x12\x11\n\x01\x66\x18\x0e \x01(\x0b\x32\x06.Value\x12\x14\n\x01g\x18\x0f \x01(\x0b\x32\t.Node2Def\x12\x11\n\x01h\x18\x10 \x03(\x0b\x32\x06.Value\x12\x14\n\x01i\x18\x11 \x03(\x0b\x32\t.Node1Def\"R\n\x08Node2Def\x12\x11\n\x01\x61\x18\x01 \x01(\x0b\x32\x06.Value\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x03(\x05\x12\n\n\x02id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"E\n\x08Node3Def\x12\x17\n\x02n1\x18\x01 \x01(\x0b\x32\t.Node1DefH\x00\x12\x17\n\x02n2\x18\x02 \x01(\x0b\x32\t.Node2DefH\x00\x42\x07\n\x05value\"b\n\x08Node4Def\x12!\n\x04\x61ttr\x18\x01 \x03(\x0b\x32\x13.Node4Def.AttrEntry\x1a\x33\n\tAttrEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x15\n\x05value\x18\x02 \x01(\x0b\x32\x06.Value:\x02\x38\x01\x62\x06proto3')
   ,
   dependencies=[mars_dot_serialize_dot_protos_dot_value__pb2.DESCRIPTOR,])
 
@@ -119,35 +120,49 @@
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='e', full_name='Node1Def.e', index=12,
+      name='cl1', full_name='Node1Def.cl1', index=12,
+      number=18, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='cl2', full_name='Node1Def.cl2', index=13,
+      number=19, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR),
+    _descriptor.FieldDescriptor(
+      name='e', full_name='Node1Def.e', index=14,
       number=13, type=8, cpp_type=7, label=1,
       has_default_value=False, default_value=False,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='f', full_name='Node1Def.f', index=13,
+      name='f', full_name='Node1Def.f', index=15,
       number=14, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='g', full_name='Node1Def.g', index=14,
+      name='g', full_name='Node1Def.g', index=16,
       number=15, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='h', full_name='Node1Def.h', index=15,
+      name='h', full_name='Node1Def.h', index=17,
       number=16, type=11, cpp_type=10, label=3,
       has_default_value=False, default_value=[],
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR),
     _descriptor.FieldDescriptor(
-      name='i', full_name='Node1Def.i', index=16,
+      name='i', full_name='Node1Def.i', index=18,
       number=17, type=11, cpp_type=10, label=3,
       has_default_value=False, default_value=[],
       message_type=None, enum_type=None, containing_type=None,
@@ -166,7 +181,7 @@
   oneofs=[
   ],
   serialized_start=74,
-  serialized_end=320,
+  serialized_end=362,
 )
 
 
@@ -224,8 +239,8 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=322,
-  serialized_end=404,
+  serialized_start=364,
+  serialized_end=446,
 )
 
 
@@ -265,8 +280,8 @@
       name='value', full_name='Node3Def.value',
       index=0, containing_type=None, fields=[]),
   ],
-  serialized_start=406,
-  serialized_end=475,
+  serialized_start=448,
+  serialized_end=517,
 )
 
 
@@ -303,8 +318,8 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=524,
-  serialized_end=575,
+  serialized_start=566,
+  serialized_end=617,
 )
 
 _NODE4DEF = _descriptor.Descriptor(
@@ -333,10 +348,12 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=477,
-  serialized_end=575,
+  serialized_start=519,
+  serialized_end=617,
 )
 
+_NODE1DEF.fields_by_name['cl1'].message_type = mars_dot_serialize_dot_protos_dot_value__pb2._VALUE
+_NODE1DEF.fields_by_name['cl2'].message_type = mars_dot_serialize_dot_protos_dot_value__pb2._VALUE
 _NODE1DEF.fields_by_name['f'].message_type = mars_dot_serialize_dot_protos_dot_value__pb2._VALUE
 _NODE1DEF.fields_by_name['g'].message_type = _NODE2DEF
 _NODE1DEF.fields_by_name['h'].message_type = mars_dot_serialize_dot_protos_dot_value__pb2._VALUE
@@ -359,39 +376,39 @@
 DESCRIPTOR.message_types_by_name['Node4Def'] = _NODE4DEF
 _sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
-Node1Def = _reflection.GeneratedProtocolMessageType('Node1Def', (_message.Message,), dict(
-  DESCRIPTOR = _NODE1DEF,
-  __module__ = 'mars.serialize.tests.testser_pb2'
+Node1Def = _reflection.GeneratedProtocolMessageType('Node1Def', (_message.Message,), {
+  'DESCRIPTOR' : _NODE1DEF,
+  '__module__' : 'mars.serialize.tests.testser_pb2'
   # @@protoc_insertion_point(class_scope:Node1Def)
-  ))
+  })
 _sym_db.RegisterMessage(Node1Def)
 
-Node2Def = _reflection.GeneratedProtocolMessageType('Node2Def', (_message.Message,), dict(
-  DESCRIPTOR = _NODE2DEF,
-  __module__ = 'mars.serialize.tests.testser_pb2'
+Node2Def = _reflection.GeneratedProtocolMessageType('Node2Def', (_message.Message,), {
+  'DESCRIPTOR' : _NODE2DEF,
+  '__module__' : 'mars.serialize.tests.testser_pb2'
   # @@protoc_insertion_point(class_scope:Node2Def)
-  ))
+  })
 _sym_db.RegisterMessage(Node2Def)
 
-Node3Def = _reflection.GeneratedProtocolMessageType('Node3Def', (_message.Message,), dict(
-  DESCRIPTOR = _NODE3DEF,
-  __module__ = 'mars.serialize.tests.testser_pb2'
+Node3Def = _reflection.GeneratedProtocolMessageType('Node3Def', (_message.Message,), {
+  'DESCRIPTOR' : _NODE3DEF,
+  '__module__' : 'mars.serialize.tests.testser_pb2'
   # @@protoc_insertion_point(class_scope:Node3Def)
-  ))
+  })
 _sym_db.RegisterMessage(Node3Def)
 
-Node4Def = _reflection.GeneratedProtocolMessageType('Node4Def', (_message.Message,), dict(
+Node4Def = _reflection.GeneratedProtocolMessageType('Node4Def', (_message.Message,), {
 
-  AttrEntry = _reflection.GeneratedProtocolMessageType('AttrEntry', (_message.Message,), dict(
-    DESCRIPTOR = _NODE4DEF_ATTRENTRY,
-    __module__ = 'mars.serialize.tests.testser_pb2'
+  'AttrEntry' : _reflection.GeneratedProtocolMessageType('AttrEntry', (_message.Message,), {
+    'DESCRIPTOR' : _NODE4DEF_ATTRENTRY,
+    '__module__' : 'mars.serialize.tests.testser_pb2'
     # @@protoc_insertion_point(class_scope:Node4Def.AttrEntry)
-    ))
+    })
   ,
-  DESCRIPTOR = _NODE4DEF,
-  __module__ = 'mars.serialize.tests.testser_pb2'
+  'DESCRIPTOR' : _NODE4DEF,
+  '__module__' : 'mars.serialize.tests.testser_pb2'
   # @@protoc_insertion_point(class_scope:Node4Def)
-  ))
+  })
 _sym_db.RegisterMessage(Node4Def)
 _sym_db.RegisterMessage(Node4Def.AttrEntry)