Repository: pydantic/pydantic

Issue:
(2.4.0) JSON Schema for Generics models with Literal as agrument is broken
### Initial Checks

- [X] I confirm that I'm using Pydantic V2

### Description

Straightforward example:

pydantic v2.3.0
```
{'$defs': {'G_Literal_str__str__': {'properties': {'foo': {'enum': ['a', 'b'],
                                                           'title': 'Foo',
                                                           'type': 'string'}},
                                    'required': ['foo'],
                                    'title': 'G[Literal[str, str]]',
                                    'type': 'object'},
           'M': {'properties': {'foo': {'enum': ['a', 'b'],
                                        'title': 'Foo',
                                        'type': 'string'}},
                 'required': ['foo'],
                 'title': 'M',
                 'type': 'object'}}}
```

pydantic v2.4.0
```
{'$defs': {'G': {'properties': {'foo': {'title': 'Foo'}},
                 'required': ['foo'],
                 'title': 'G',
                 'type': 'object'},
           'M': {'properties': {'foo': {'enum': ['a', 'b'],
                                        'title': 'Foo',
                                        'type': 'string'}},
                 'required': ['foo'],
                 'title': 'M',
                 'type': 'object'}}}
```


### Example Code

```Python
from pprint import pprint
from pydantic import BaseModel, RootModel
from pydantic.json_schema import models_json_schema
from typing import Generic, TypeVar, Literal

T = TypeVar('T')

class G(BaseModel, Generic[T]):
	foo: T

class M(BaseModel):
	foo: Literal['a', 'b']

pprint(models_json_schema([
	(G[Literal['a', 'b']], 'serialization'),
	(G[Literal['a', 'b']], 'validation'),
	(M, 'validation'),
])[1])
```


### Python, Pydantic & OS Version

```Text
venv ❯ python -c "import pydantic.version; print(pydantic.version.version_info())"
             pydantic version: 2.4.0
        pydantic-core version: 2.10.0
          pydantic-core build: profile=release pgo=true
                 install path: /opt/projects/tradingview/venv/lib/python3.11/site-packages/pydantic
               python version: 3.11.5 (main, Aug 25 2023, 13:19:50) [GCC 11.4.0]
                     platform: Linux-6.2.0-33-generic-x86_64-with-glibc2.35
             related packages: typing_extensions-4.7.1 mypy-1.0.1

Works if I downgrade to
             pydantic version: 2.3.0
        pydantic-core version: 2.6.3
```



Discussion:
Actually I think all generics lost its type arguments:
```
pprint(models_json_schema([
	(G[int], 'serialization'),
	(G[float], 'validation'),
	(M, 'validation'),
])[1])
```
does not generate any type for field `foo` too
Thanks @bogdandm for reporting this 🙏 

We will provide a fix for this

Resolving patch:
diff --git a/pydantic/_internal/_repr.py b/pydantic/_internal/_repr.py
--- a/pydantic/_internal/_repr.py
+++ b/pydantic/_internal/_repr.py
@@ -101,7 +101,10 @@ def display_as_type(obj: Any) -> str:
         args = ', '.join(map(display_as_type, typing_extensions.get_args(obj)))
         return f'Union[{args}]'
     elif isinstance(obj, _typing_extra.WithArgsTypes):
-        args = ', '.join(map(display_as_type, typing_extensions.get_args(obj)))
+        if typing_extensions.get_origin(obj) == typing_extensions.Literal:
+            args = ', '.join(map(repr, typing_extensions.get_args(obj)))
+        else:
+            args = ', '.join(map(display_as_type, typing_extensions.get_args(obj)))
         return f'{obj.__qualname__}[{args}]'
     elif isinstance(obj, type):
         return obj.__qualname__
diff --git a/pydantic/json_schema.py b/pydantic/json_schema.py
--- a/pydantic/json_schema.py
+++ b/pydantic/json_schema.py
@@ -2180,6 +2180,10 @@ def models_json_schema(
             - The second element is a JSON schema containing all definitions referenced in the first returned
                     element, along with the optional title and description keys.
     """
+    for cls, _ in models:
+        if isinstance(cls.__pydantic_validator__, _mock_val_ser.MockValSer):
+            cls.__pydantic_validator__.rebuild()
+
     instance = schema_generator(by_alias=by_alias, ref_template=ref_template)
     inputs = [(m, mode, m.__pydantic_core_schema__) for m, mode in models]
     json_schemas_map, definitions = instance.generate_definitions(inputs)


Test patch:
diff --git a/tests/test_json_schema.py b/tests/test_json_schema.py
--- a/tests/test_json_schema.py
+++ b/tests/test_json_schema.py
@@ -5629,6 +5629,46 @@ class SerializationModel(Model):
     assert SerializationModel.model_json_schema(mode='validation') == Model.model_json_schema(mode='serialization')
 
 
+def test_models_json_schema_generics() -> None:
+    class G(BaseModel, Generic[T]):
+        foo: T
+
+    class M(BaseModel):
+        foo: Literal['a', 'b']
+
+    GLiteral = G[Literal['a', 'b']]
+
+    assert models_json_schema(
+        [
+            (GLiteral, 'serialization'),
+            (GLiteral, 'validation'),
+            (M, 'validation'),
+        ]
+    ) == (
+        {
+            (GLiteral, 'serialization'): {'$ref': '#/$defs/G_Literal__a____b___'},
+            (GLiteral, 'validation'): {'$ref': '#/$defs/G_Literal__a____b___'},
+            (M, 'validation'): {'$ref': '#/$defs/M'},
+        },
+        {
+            '$defs': {
+                'G_Literal__a____b___': {
+                    'properties': {'foo': {'enum': ['a', 'b'], 'title': 'Foo', 'type': 'string'}},
+                    'required': ['foo'],
+                    'title': "G[Literal['a', 'b']]",
+                    'type': 'object',
+                },
+                'M': {
+                    'properties': {'foo': {'enum': ['a', 'b'], 'title': 'Foo', 'type': 'string'}},
+                    'required': ['foo'],
+                    'title': 'M',
+                    'type': 'object',
+                },
+            }
+        },
+    )
+
+
 def test_recursive_non_generic_model() -> None:
     class Foo(BaseModel):
         maybe_bar: Union[None, 'Bar']