Repository: fuhrysteve/marshmallow-jsonschema

Issue:
Default field values may be callable
When building the json schema from a marshmallow schema, with a default value being a callable, the resulting schema is not clean to pass to `json.dumps()` for instance.

https://github.com/fuhrysteve/marshmallow-jsonschema/blob/8e70c7e3262eb5ce8a34462e9ebbc08b90201afb/marshmallow_jsonschema/base.py#L191

Example
```python
import json
import uuid
from marshmallow import Schema, fields
from marshmallow_jsonschema import JSONSchema

class Test(Schema):
    id = fields.UUID(default=uuid.uuid1)

json.dumps(JSONSchema().dump(Test()))
# >> TypeError: Object of type function is not JSON serializable


# JSONSchema().dump(Test()) >> 
{'$schema': 'http://json-schema.org/draft-07/schema#',
 'definitions': {'Test': {'properties': {'id': {'title': 'id',
     'type': 'string',
     'default': <function uuid.uuid1(node=None, clock_seq=None)>}},
   'type': 'object',
   'additionalProperties': False}},
 '$ref': '#/definitions/Test'}

```

Both `missing` and `default` may be callable values for marshmallow fields: https://marshmallow.readthedocs.io/en/stable/marshmallow.fields.html#marshmallow.fields.Field


Comments:

Patch:
diff --git a/marshmallow_jsonschema/base.py b/marshmallow_jsonschema/base.py
index 55c0360..a8fb726 100644
--- a/marshmallow_jsonschema/base.py
+++ b/marshmallow_jsonschema/base.py
@@ -187,7 +187,7 @@ class JSONSchema(Schema):
         if field.dump_only:
             json_schema["readOnly"] = True
 
-        if field.default is not missing:
+        if field.default is not missing and not callable(field.default):
             json_schema["default"] = field.default
 
         if ALLOW_ENUMS and isinstance(field, EnumField):
@@ -324,6 +324,9 @@ class JSONSchema(Schema):
                 continue
             schema[md_key] = md_val
 
+        if field.default is not missing and not callable(field.default):
+            schema["default"] = nested_instance.dump(field.default)
+
         if field.many:
             schema = {
                 "type": "array" if field.required else ["array", "null"],


Test patch:
diff --git a/tests/test_dump.py b/tests/test_dump.py
index e862491..ca3f316 100644
--- a/tests/test_dump.py
+++ b/tests/test_dump.py
@@ -1,3 +1,4 @@
+import uuid
 from enum import Enum
 
 import pytest
@@ -30,6 +31,18 @@ def test_default():
     assert props["id"]["default"] == "no-id"
 
 
+def test_default_callable_not_serialized():
+    class TestSchema(Schema):
+        uid = fields.UUID(default=uuid.uuid4)
+
+    schema = TestSchema()
+
+    dumped = validate_and_dump(schema)
+
+    props = dumped["definitions"]["TestSchema"]["properties"]
+    assert "default" not in props["uid"]
+
+
 def test_uuid():
     schema = UserSchema()
 
@@ -307,6 +320,26 @@ def test_respect_dotted_exclude_for_nested_schema():
     assert "recursive" not in inner_props
 
 
+def test_respect_default_for_nested_schema():
+    class TestNestedSchema(Schema):
+        myfield = fields.String()
+        yourfield = fields.Integer(required=True)
+
+    nested_default = {"myfield": "myval", "yourfield": 1}
+
+    class TestSchema(Schema):
+        nested = fields.Nested(
+            TestNestedSchema,
+            default=nested_default,
+        )
+        yourfield_nested = fields.Integer(required=True)
+
+    schema = TestSchema()
+    dumped = validate_and_dump(schema)
+    default = dumped["definitions"]["TestSchema"]["properties"]["nested"]["default"]
+    assert default == nested_default
+
+
 def test_nested_instance():
     """Should also work with nested schema instances"""