Repository: line/line-bot-sdk-python

Issue:
Can't send FlexMessage with Hero block
## System Informations

* Python version: 3.7.7
* SDK version: 1.16.0
* OS: macOS Mojave 10.14.3

## Expected Behavior
The docs say that box or image can be used for hero block.
https://developers.line.biz/en/reference/messaging-api/#bubble
> Hero block. Specify a box or an image.

## Current Behavior
<!-- Tell us what happens instead of the expected behavior -->
I tried to send FlexMessage with box block, but got an error.
```
e.status_code: 400
e.error.message: A message (messages[0]) in the request body is invalid
e.error.details: [{"message": "must be specified", "property": "/hero/url"}]
```

Hero seems to be initialized with ImageComponent if I pass in a json.
https://github.com/line/line-bot-sdk-python/blob/9e9b1f9fd0dc577fe79dd288d9234407f0f25470/linebot/models/flex_message.py#L112

Probably this question also has the same error.
https://www.line-community.me/question/5e7b039a851f7402cd963e3c

## Steps to Reproduce
<!-- Provide a link to a live example, or an unambigeous set of steps to -->
1. change parameters and execute following script.
```python
from linebot import LineBotApi
from linebot.models import FlexSendMessage
from linebot.exceptions import LineBotApiError

# fail and output following
#
#    e.status_code: 400
#    e.error.message: A message (messages[0]) in the request body is invalid
#    e.error.details: [{"message": "must be specified", "property": "/hero/url"}]
messages = [{
  'type': 'flex',
  'altText': 'altText',
  'contents':
  {
    'type': 'bubble',
    'hero': {
      'type': 'box',
      'layout': 'vertical',
      'contents': [
        {
          'type': 'text',
          'text': 'Brown Cafe'
        }
      ]
    }
  }
}]

# success if change "hero" to "body"
#
#   messages = [{
#     'type': 'flex',
#     'altText': 'altText',
#     'contents':
#     {
#       'type': 'bubble',
#       'body': {
#         'type': 'box',
#         'layout': 'vertical',
#         'contents': [
#           {
#             'type': 'text',
#             'text': 'Brown Cafe'
#           }
#         ]
#       }
#     }
#   }]

# success if change hero's child element from "box" to "image"
#
#   messages = [{
#     'type': 'flex',
#     'altText': 'altText',
#     'contents':
#     {
#       'type': 'bubble',
#       'hero': {
#         'type': 'image',
#         'url': 'VALID URL',
#       }
#     }
#   }]

user_id = ''
channel_access_token = ''

line_bot_api = LineBotApi(channel_access_token)
flex_messages = [FlexSendMessage(alt_text=message['altText'], contents=message['contents']) for message in messages]

try:
  line_bot_api.push_message(user_id, flex_messages)
except LineBotApiError as e:
    print('e.status_code:', e.status_code)
    print('e.error.message:',e.error.message)
    print('e.error.details:',e.error.details)
```

## Logs
<!-- Provide logs if possible -->


Discussion:

Patch:
diff --git a/linebot/models/flex_message.py b/linebot/models/flex_message.py
index afccc3e..bd95169 100644
--- a/linebot/models/flex_message.py
+++ b/linebot/models/flex_message.py
@@ -109,7 +109,12 @@ class BubbleContainer(FlexContainer):
         self.size = size
         self.direction = direction
         self.header = self.get_or_new_from_json_dict(header, BoxComponent)
-        self.hero = self.get_or_new_from_json_dict(hero, ImageComponent)
+        self.hero = self.get_or_new_from_json_dict_with_types(
+            hero, {
+                'image': ImageComponent,
+                'box': BoxComponent
+            }
+        )
         self.body = self.get_or_new_from_json_dict(body, BoxComponent)
         self.footer = self.get_or_new_from_json_dict(footer, BoxComponent)
         self.styles = self.get_or_new_from_json_dict(styles, BubbleStyle)


Test patch:
diff --git a/tests/models/test_flex_message.py b/tests/models/test_flex_message.py
index ad752fc..9fe7c29 100644
--- a/tests/models/test_flex_message.py
+++ b/tests/models/test_flex_message.py
@@ -61,8 +61,6 @@ class TestFlexMessage(SerializeTestCase):
             'header':
                 BoxComponent(layout='vertical',
                              contents=[TextComponent(text='Header text')]),
-            'hero':
-                ImageComponent(uri='https://example.com/flex/images/image.jpg'),
             'body':
                 BoxComponent(layout='vertical',
                              contents=[TextComponent(text='Body text')]),
@@ -79,10 +77,17 @@ class TestFlexMessage(SerializeTestCase):
                                       separator_color='#00ffff')
                 )
         }
-        self.assertEqual(
-            self.serialize_as_dict(arg, type=self.BUBBLE),
-            BubbleContainer(**arg).as_json_dict()
-        )
+        heros = [
+            ImageComponent(uri='https://example.com/flex/images/image.jpg'),
+            BoxComponent(layout='vertical',
+                         contents=[TextComponent(text='Body text')]),
+        ]
+        for hero in heros:
+            arg['hero'] = hero
+            self.assertEqual(
+                self.serialize_as_dict(arg, type=self.BUBBLE),
+                BubbleContainer(**arg).as_json_dict()
+            )
 
     def test_bubble_style(self):
         arg = {