Repository: lidatong/dataclasses-json

Issue:
`to_dict(encode_json=True)` is not recursive
I expect `to_dict(encode_json=True)` to be recursive, however the code below evaluates to:
```
{'engine': 'fast', 'wheels': [<Spec.fast: 'fast'>, <Spec.slow: 'slow'>]}
```
The first level of Enums evaluate to strings as expected, but the list is not JSON encoded. I expected it to be:
```
{'engine': 'fast', 'wheels': ['fast', 'slow']}
```

```
from dataclasses import dataclass
from enum import Enum
from typing import List
from dataclasses_json import DataClassJsonMixin

class Spec(Enum):
    fast = 'fast'
    slow = 'slow'

@dataclass
class Car(DataClassJsonMixin):
    engine: Spec
    wheels: List[Spec]

car = Car(engine=Spec.fast, wheels=[Spec.fast, Spec.slow])

car.to_dict(encode_json=True)
```

My current work-around is:
```
import json

json.loads(car.to_json())
```
However, this is not as nice

Discussion:
AbsurdlySuspicious: Wouldn't this still fail on dicts or lists with more than one level of nesting? I believe this type check should be done in `_encode_json_type` to be properly recursive
matt035343: @AbsurdlySuspicious

> Wouldn't this still fail on dicts and lists with more than one level of nesting? I believe this type check should be done in `_encode_json_type` to be properly recursive

You are absolutely right. I have now fixed it and changed the test to catch this case as well.

george-zubrienko: @matt035343 could you sync your branch with master, so CI runs again w/o py3.6?

Patch:
diff --git a/dataclasses_json/core.py b/dataclasses_json/core.py
index 529e153..ae1e99b 100644
--- a/dataclasses_json/core.py
+++ b/dataclasses_json/core.py
@@ -93,7 +93,12 @@ def _user_overrides_or_exts(cls):
 
 def _encode_json_type(value, default=_ExtendedEncoder().default):
     if isinstance(value, Json.__args__):  # type: ignore
-        return value
+        if isinstance(value, list):
+            return [_encode_json_type(i) for i in value]
+        elif isinstance(value, dict):
+            return {k: _encode_json_type(v) for k, v in value.items()}
+        else:
+            return value
     return default(value)
 
 


Test patch:
diff --git a/tests/test_enum.py b/tests/test_enum.py
index 6d0ce82..f4848ed 100644
--- a/tests/test_enum.py
+++ b/tests/test_enum.py
@@ -1,9 +1,9 @@
 import json
 from enum import Enum
-from typing import Dict, List
+from typing import Dict, List, Optional
 import pytest
 
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 
 from dataclasses_json import dataclass_json
 
@@ -27,19 +27,25 @@ class MyStrEnum(str, Enum):
 class DataWithEnum:
     name: str
     my_enum: MyEnum = MyEnum.STR3
+    enum_list: List[MyEnum] = field(default_factory=list)
+    nested: Dict[str, List[MyEnum]] = field(default_factory=dict)
 
 
 d1 = DataWithEnum('name1', MyEnum.STR1)
-d1_json = '{"name": "name1", "my_enum": "str1"}'
+d1_json = '{"name": "name1", "my_enum": "str1", "enum_list": [], "nested": {}}'
 
 # Make sure the enum is set to the default value defined by MyEnum
 d2_using_default_value = DataWithEnum('name2')
-d2_json = '{"name": "name2", "my_enum": "str3"}'
+d2_json = '{"name": "name2", "my_enum": "str3", "enum_list": [], "nested": {}}'
 
 d3_int = DataWithEnum('name1', MyEnum.INT1)
-d3_int_json = '{"name": "name1", "my_enum": 1}'
+d3_int_json = '{"name": "name1", "my_enum": 1, "enum_list": [], "nested": {}}'
+
 d4_float = DataWithEnum('name1', MyEnum.FLOAT1)
-d4_float_json = '{"name": "name1", "my_enum": 1.23}'
+d4_float_json = '{"name": "name1", "my_enum": 1.23, "enum_list": [], "nested": {}}'
+
+d5_list = DataWithEnum('name1', MyEnum.STR1, [MyEnum.STR2, MyEnum.STR3], nested={'enum_val': [MyEnum.STR1]})
+d5_list_json = '{"name": "name1", "my_enum": "str1", "enum_list": ["str2", "str3"], "nested": {"enum_val": ["str1"]}}'
 
 
 @dataclass_json
@@ -82,6 +88,10 @@ class TestEncoder:
     def test_collection_with_enum(self):
         assert container.to_json() == container_json
 
+    def test_enum_with_list(self):
+        assert d5_list.to_json() == d5_list_json, f'Actual: {d5_list.to_json()}, Expected: {d5_list_json}'
+        assert d5_list.to_dict(encode_json=True) == json.loads(d5_list_json), f'Actual: {d5_list.to_dict()}, Expected: {json.loads(d5_list_json)}'
+
 
 class TestDecoder:
     def test_data_with_enum(self):