Repository: koxudaxi/datamodel-code-generator

Issue:
null bytes (`\u0000`) not correctly escaped in generated code
**Describe the bug**
A schema containing a NUL character `\u0000` becomes a literal (i.e. not escaped) NUL in the generated Python file. This is a SyntaxError.

> SyntaxError: source code cannot contain null bytes

**To Reproduce**

Example schema:
```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "bug": {
      "type": "string",
      "enum": ["\u0000"]
    }
  },
  "type": "object"
}
```

Used commandline:
```
$ datamodel-codegen --input-file-type jsonschema --input schema.json --output-model-type pydantic_v2.BaseModel --output model.py
$ python -i model.py
```

**Expected behavior**
Bytes invalid in source code should use the appropriate escape sequence.

**Version:**
 - OS: macOS 13.0.1
 - Python version: 3.11
 - datamodel-code-generator version: 0.25.3

**Additional context**
I first encountered it with regex pattern properties, but it appears to be a general issue with just strings.
Notably this applies to all output-model-types with the exception of `typing.TypedDict`, where it's correctly escaped to `'\x00'` in Literal.

Hints from issue comments:

Solution patch:
diff --git a/README.md b/README.md
index ed731de9..92441206 100644
--- a/README.md
+++ b/README.md
@@ -460,7 +460,7 @@ Model customization:
                         pydantic: datetime, dataclass: str, ...)
   --reuse-model         Reuse models on the field when a module has the model with the same
                         content
-  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12}
+  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13}
                         target python version (default: 3.8)
   --treat-dot-as-module
                         treat dotted module names as modules
diff --git a/datamodel_code_generator/parser/base.py b/datamodel_code_generator/parser/base.py
index c89a2573..874b64c0 100644
--- a/datamodel_code_generator/parser/base.py
+++ b/datamodel_code_generator/parser/base.py
@@ -65,6 +65,7 @@ def get_special_path(keyword: str, path: List[str]) -> List[str]:
 
 escape_characters = str.maketrans(
     {
+        '\u0000': r'\x00',  # Null byte
         '\\': r'\\',
         "'": r'\'',
         '\b': r'\b',
diff --git a/docs/index.md b/docs/index.md
index 6d2d8127..c4f4994e 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -454,7 +454,7 @@ Model customization:
                         pydantic: datetime, dataclass: str, ...)
   --reuse-model         Reuse models on the field when a module has the model with the same
                         content
-  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12}
+  --target-python-version {3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13}
                         target python version (default: 3.8)
   --treat-dot-as-module
                         treat dotted module names as modules


Test patch:
diff --git a/tests/parser/test_base.py b/tests/parser/test_base.py
index 83fdb46e..a36951f1 100644
--- a/tests/parser/test_base.py
+++ b/tests/parser/test_base.py
@@ -7,6 +7,7 @@ from datamodel_code_generator.model import DataModel, DataModelFieldBase
 from datamodel_code_generator.model.pydantic import BaseModel, DataModelField
 from datamodel_code_generator.parser.base import (
     Parser,
+    escape_characters,
     exact_import,
     relative,
     sort_data_models,
@@ -284,3 +285,34 @@ def test_no_additional_imports():
 def test_postprocess_result_modules(input_data, expected):
     result = Parser._Parser__postprocess_result_modules(input_data)
     assert result == expected
+
+
+@pytest.fixture
+def escape_map() -> Dict[str, str]:
+    return {
+        '\u0000': r'\x00',  # Null byte
+        "'": r'\'',
+        '\b': r'\b',
+        '\f': r'\f',
+        '\n': r'\n',
+        '\r': r'\r',
+        '\t': r'\t',
+        '\\': r'\\',
+    }
+
+
+@pytest.mark.parametrize(
+    'input_str,expected',
+    [
+        ('\u0000', r'\x00'),  # Test null byte
+        ("'", r'\''),  # Test single quote
+        ('\b', r'\b'),  # Test backspace
+        ('\f', r'\f'),  # Test form feed
+        ('\n', r'\n'),  # Test newline
+        ('\r', r'\r'),  # Test carriage return
+        ('\t', r'\t'),  # Test tab
+        ('\\', r'\\'),  # Test backslash
+    ],
+)
+def test_character_escaping(input_str: str, expected: str) -> None:
+    assert input_str.translate(escape_characters) == expected