2022/12/20

swagger-py-codegen, modify source, build and test

因為在 api yaml 中有 date-time 型別,做 codegen 時加上 --spec (因為要 run swagger-ui),就會出現 Error:
    raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type date is not JSON serializable
查。這邊 ,和這邊,都說是因為用 python 內建的 json package,在對 datetime 做 dump 時出現的 error。

所以自己寫一個tostring 的 class
from datetime import datetime,date

class myobjtostr(json.JSONEncoder):
    
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        
        if isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, obj)
然後在call dump 的地方改成:
      json.dumps(mydata, cls=myobjtostr)

出現Error 的地方式..
  File "/home/charles-chang/miniconda3/envs/swagger3.7/lib/python3.7/site-packages/swagger_py_codegen/command.py", line 200, in generate
    for code in generator.generate():
  File "/home/charles-chang/miniconda3/envs/swagger3.7/lib/python3.7/site-packages/swagger_py_codegen/base.py", line 47, in generate
    for code in self._process():
  File "/home/charles-chang/miniconda3/envs/swagger3.7/lib/python3.7/site-packages/swagger_py_codegen/flask.py", line 216, in _process
    yield Specification(dict(swagger=json.dumps(swagger, indent=2)))
所以是 flask.py line 216
修改:
diff --git a/swagger_py_codegen/flask.py b/swagger_py_codegen/flask.py
index 92f58c8..589bedf 100644
--- a/swagger_py_codegen/flask.py
+++ b/swagger_py_codegen/flask.py
@@ -6,6 +6,8 @@ from .base import Code, CodeGenerator
 from .jsonschema import Schema, SchemaGenerator, build_default
 import six

+from datetime import date,datetime
+
 SUPPORT_METHODS = ['get', 'post', 'put', 'delete', 'patch', 'options', 'head']


@@ -116,6 +118,15 @@ def _location(swagger_location):
     }
     return location_map.get(swagger_location)

+import json
+class myobj2str(json.JSONEncoder):
+    def default(self, obj):
+        if isinstance(obj, datetime):
+            return obj.strftime('%Y-%m-%d %H:%M:%S')
+        if isinstance(obj, date):
+            return obj.strftime('%Y-%m-%d')
+        else:
+            return json.JSONEncoder.default(self.obj)

 class FlaskGenerator(CodeGenerator):
     dependencies = [SchemaGenerator]
@@ -213,7 +224,7 @@ class FlaskGenerator(CodeGenerator):
             swagger.update(self.swagger.origin_data)
             swagger.pop('host', None)
             swagger.pop('schemes', None)
-            yield Specification(dict(swagger=json.dumps(swagger, indent=2)))
+            yield Specification(dict(swagger=json.dumps(swagger, indent=2,cls=myobj2str)))

         yield Validator()

修改完後,follow 這一篇,用source code 中寫好的 setup.py 來 test build and run.
其中 developement mode:
$ python setup.py develop
這樣就可以run swagger_py_codegen,而且是 run 在 swagger-py-codegen 里的 code。
所以如果有錯,直接修改就可以。
不用再 install (run setup.py)

這樣改完的確不會再發生 error

改完的code:
另外,不知什麼原因,有的python 環境有simplejson 的會出現 error : module simplejson has no dump()。
所以要修改:
diff --git a/swagger_py_codegen/flask.py b/swagger_py_codegen/flask.py
index 403df02..8c51936 100644
--- a/swagger_py_codegen/flask.py
+++ b/swagger_py_codegen/flask.py
@@ -216,10 +216,7 @@ class FlaskGenerator(CodeGenerator):
         for view in views:
             yield View(view, dist_env=dict(view=view['endpoint']))
         if self.with_spec:
-            try:
-                import simplejson as json
-            except ImportError:
-                import json
+            import json
             swagger = {}
             swagger.update(self.swagger.origin_data)
             swagger.pop('host', None)
不要用 simplejson。

沒有留言:

張貼留言