Repository: Fatal1ty/mashumaro

Issue:
JSON Schema generator doesn't honor `default_factory`
* mashumaro version: 3.7
* Python version: 3.11 (but 3.10 is the same)
* Operating System: macOS Ventura

### Description

See the full code and output below. When using default value, directly or via `field(default=...)` the schema correctly recognizes the field as not required. But it doesn't work with `default_factory` unfortunately.

Shall I open a PR?

### What I Did

```
import json
from dataclasses import dataclass, field
from functools import partial

from mashumaro import DataClassDictMixin
from mashumaro.jsonschema import build_json_schema


@dataclass
class Foo(DataClassDictMixin):
    bar: frozenset[str] = field(default_factory=frozenset)


print(build_json_schema(Foo).to_json(encoder=partial(json.dumps, indent=2)))
# {
#   "type": "object",
#   "title": "Foo",
#   "properties": {
#     "bar": {
#       "type": "array",
#       "items": {
#         "type": "string"
#       },
#       "uniqueItems": true
#     }
#   },
#   "additionalProperties": false,
#   "required": [
#     "bar"
#   ]
# }

```


Discussion:

Patch:
diff --git a/mashumaro/jsonschema/schema.py b/mashumaro/jsonschema/schema.py
index 90fa19f..65c3ec3 100644
--- a/mashumaro/jsonschema/schema.py
+++ b/mashumaro/jsonschema/schema.py
@@ -154,7 +154,7 @@ class Instance:
             self.__builder = CodeBuilder(self.origin_type, type_args)
             self.__builder.reset()
 
-    def fields(self) -> Iterable[Tuple[str, Type, Any]]:
+    def fields(self) -> Iterable[Tuple[str, Type, bool, Any]]:
         for f_name, f_type in self._builder.get_field_types(
             include_extras=True
         ).items():
@@ -166,7 +166,12 @@ class Instance:
                 f_default = self._builder.namespace.get(f_name, MISSING)
             if f_default is not MISSING:
                 f_default = _default(f_type, f_default)
-            yield f_name, f_type, f_default
+
+            has_default = (
+                f.default is not MISSING or f.default_factory is not MISSING
+            )
+
+            yield f_name, f_type, has_default, f_default
 
     def get_overridden_serialization_method(
         self,
@@ -289,7 +294,7 @@ def on_dataclass(instance: Instance, ctx: Context) -> Optional[JSONSchema]:
         field_schema_overrides = instance.get_config().json_schema.get(
             "properties", {}
         )
-        for f_name, f_type, f_default in instance.fields():
+        for f_name, f_type, has_default, f_default in instance.fields():
             override = field_schema_overrides.get(f_name)
             f_instance = instance.copy(type=f_type, name=f_name)
             if override:
@@ -301,8 +306,10 @@ def on_dataclass(instance: Instance, ctx: Context) -> Optional[JSONSchema]:
                 f_name = f_instance.alias
             if f_default is not MISSING:
                 f_schema.default = f_default
-            else:
+
+            if not has_default:
                 required.append(f_name)
+
             properties[f_name] = f_schema
         if properties:
             schema.properties = properties


Test patch:
diff --git a/tests/test_jsonschema/test_jsonschema_generation.py b/tests/test_jsonschema/test_jsonschema_generation.py
index 875d719..626f977 100644
--- a/tests/test_jsonschema/test_jsonschema_generation.py
+++ b/tests/test_jsonschema/test_jsonschema_generation.py
@@ -126,6 +126,7 @@ def test_jsonschema_for_dataclass():
         c: Optional[int] = field(default=None, metadata={"alias": "cc"})
         d: str = ""
         e: int = field(init=False)
+        f: List[int] = field(default_factory=list)
 
         class Config:
             aliases = {"a": "aa", "d": "dd"}
@@ -143,6 +144,9 @@ def test_jsonschema_for_dataclass():
                 default=None,
             ),
             "dd": JSONSchema(type=JSONSchemaInstanceType.STRING, default=""),
+            "f": JSONArraySchema(
+                items=JSONSchema(type=JSONSchemaInstanceType.INTEGER)
+            ),
         },
         additionalProperties=False,
         required=["aa"],