Oh MyUtils

JSON to Python - Generate Dataclasses & Pydantic Models Online

Convert JSON to Python dataclasses, Pydantic BaseModel, or TypedDict with type inference, snake_case conversion, and date detection — 100% in your browser.

Root Name
Format
Syntax
Flags
JSON Input
Python Output
 

Frequently Asked Questions

What is a JSON to Python converter?

A JSON to Python converter is a tool that automatically generates Python class definitions from JSON data. Instead of manually writing dataclasses or Pydantic models with field names and type annotations, you paste a sample JSON object and the tool infers the correct Python types for every field. It supports multiple output formats: Python dataclasses (standard library), Pydantic BaseModel (with built-in validation), and TypedDict (lightweight type hints). The tool handles nested objects, arrays, null values, and follows Python naming conventions.

How do I generate Python classes from JSON?

Paste your JSON data into the input field on the left side. The tool instantly generates Python code in the output panel on the right. Choose your preferred output format (dataclass, Pydantic BaseModel, or TypedDict) using the format selector. You can customize the output by setting the root class name, enabling snake_case conversion, marking null values as Optional, and toggling date/datetime detection. Click 'Copy' to copy the generated code to your clipboard.

Should I use dataclass or Pydantic BaseModel?

Use Python dataclasses when you need a simple, dependency-free data container with type annotations. Dataclasses are part of the standard library (Python 3.7+) and have no runtime validation overhead. Use Pydantic BaseModel when you need runtime data validation, automatic type coercion, JSON serialization/deserialization, and alias support. Pydantic is especially popular with FastAPI for API request/response models. Use TypedDict when you only need type hints for dictionary-like data without runtime overhead.

Does this tool support Pydantic v2?

Yes, this tool generates Pydantic v2 code exclusively. It uses the modern Pydantic v2 syntax including model_config = ConfigDict(...) instead of the legacy class Config pattern, and follows all Pydantic v2 best practices. When snake_case conversion is enabled, it generates Field(alias='originalKey') with model_config = ConfigDict(populate_by_name=True) so your models work with both snake_case Python attributes and the original camelCase JSON keys.

Is my JSON data secure when using this tool?

Yes, completely. This tool processes everything in your browser using client-side JavaScript. Your JSON data never leaves your computer — there are no server uploads, no API calls, and no data storage. This makes it safe to use with sensitive API responses, proprietary data schemas, internal microservice contracts, and confidential configuration files.

How does the tool handle null and optional fields?

When a JSON field has a null value, the tool marks it as Optional with a default of None. For modern Python syntax (3.10+), this becomes 'field_name: str | None = None'. For legacy syntax, it uses 'field_name: Optional[str] = None'. You can also enable the 'All optional' toggle to mark every field as optional, which is useful for generating partial update models (e.g., PATCH request bodies).

How are nested JSON objects handled?

Each nested JSON object is converted into a separate named class. For example, if your JSON has a 'user' object with an 'address' sub-object, the tool creates both a 'User' class and an 'Address' class, with 'User' referencing 'Address' as a field type. Classes are ordered correctly in the output so that dependencies appear before the classes that reference them.

Code Examples

// JSON to Python dataclass/Pydantic generator
function jsonToPython(json, rootName = 'Root', format = 'dataclass') {
  const classes = [];

  function toPascalCase(str) {
    return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
              .replace(/^./, s => s.toUpperCase());
  }

  function toSnakeCase(str) {
    return str.replace(/([A-Z])/g, '_$1').replace(/^_/, '').toLowerCase();
  }

  function inferType(value, name) {
    if (value === null) return 'None';
    if (typeof value === 'boolean') return 'bool';
    if (typeof value === 'number') {
      return Number.isInteger(value) ? 'int' : 'float';
    }
    if (typeof value === 'string') return 'str';
    if (Array.isArray(value)) {
      if (value.length === 0) return 'list[Any]';
      return `list[${inferType(value[0], name)}]`;
    }
    if (typeof value === 'object') {
      const className = toPascalCase(name);
      const fields = Object.entries(value).map(([key, val]) => {
        const pyType = inferType(val, key);
        const fieldName = toSnakeCase(key);
        if (format === 'pydantic' && fieldName !== key) {
          return `    ${fieldName}: ${pyType} = Field(alias="${key}")`;
        }
        return `    ${fieldName}: ${pyType}`;
      });

      if (format === 'dataclass') {
        classes.push(`@dataclass\nclass ${className}:\n${fields.join('\n')}`);
      } else if (format === 'pydantic') {
        classes.push(`class ${className}(BaseModel):\n${fields.join('\n')}`);
      } else {
        classes.push(`class ${className}(TypedDict):\n${fields.join('\n')}`);
      }
      return className;
    }
    return 'Any';
  }

  const parsed = JSON.parse(json);
  inferType(parsed, rootName);
  return classes.reverse().join('\n\n');
}

// Example
const json = '{"userName": "alice", "age": 30, "address": {"city": "NYC"}}';
console.log(jsonToPython(json, 'User', 'pydantic'));
// Output:
// class Address(BaseModel):
//     city: str
//
// class User(BaseModel):
//     user_name: str = Field(alias="userName")
//     age: int
//     address: Address

Related Tools