import json
import os
TYPE_MAPPING = {
"string": "String",
"integer": "Integer",
"number": "Double",
"boolean": "Boolean",
}
BEAN_VALIDATION_IMPORTS = {
"NotNull": "javax.validation.constraints.NotNull",
"Size": "javax.validation.constraints.Size",
}
JPA_IMPORTS = {
"Id": "javax.persistence.Id",
"Column": "javax.persistence.Column"
}
def capitalize(s):
return s[0].upper() + s[1:] if s else s
def generate_class(name, schema, indent=0):
indent_str = " " * indent
lines = []
imports = set()
lines.append(f"{indent_str}public class {name} " + "{")
properties = schema.get("properties", {})
required = schema.get("required", [])
for prop, prop_schema in properties.items():
java_type, nested_imports, nested_classes = get_java_type(prop, prop_schema, indent + 1)
imports.update(nested_imports)
# Collect annotations
annotations = []
# Jackson annotation
annotations.append(f'@com.fasterxml.jackson.annotation.JsonProperty("{prop}")')
# Bean Validation
if prop in required:
annotations.append("@NotNull")
imports.add(BEAN_VALIDATION_IMPORTS["NotNull"])
max_length = prop_schema.get("maxLength")
if max_length is not None and java_type == "String":
annotations.append(f"@Size(max = {max_length})")
imports.add(BEAN_VALIDATION_IMPORTS["Size"])
# JPA Primary key
if prop_schema.get("primaryKey", False):
annotations.append("@Id")
imports.add(JPA_IMPORTS["Id"])
# Optionally @Column annotation for length if string
col_ann = "@Column("
col_params = []
if max_length is not None and java_type == "String":
col_params.append(f"length = {max_length}")
if col_params:
col_ann += ", ".join(col_params)
col_ann += ")"
annotations.append(col_ann)
imports.add(JPA_IMPORTS["Column"])
# Write annotations
for ann in annotations:
lines.append(f"{indent_str} {ann}")
lines.extend(nested_classes)
lines.append(f"{indent_str} private {java_type} {prop};\n")
# Getters and setters
for prop, prop_schema in properties.items():
java_type, _, _ = get_java_type(prop, prop_schema, indent + 1)
prop_camel = capitalize(prop)
# Getter
lines.append(f"{indent_str} public {java_type} get{prop_camel}() " + "{")
lines.append(f"{indent_str} return {prop};")
lines.append(f"{indent_str} }}\n")
# Setter
lines.append(f"{indent_str} public void set{prop_camel}({java_type} {prop}) " + "{")
lines.append(f"{indent_str} this.{prop} = {prop};")
lines.append(f"{indent_str} }}\n")
lines.append(f"{indent_str}}}")
return imports, lines
def get_java_type(prop_name, prop_schema, indent):
imports = set()
nested_classes = []
if "enum" in prop_schema:
enum_name = capitalize(prop_name)
enum_lines = generate_enum(enum_name, prop_schema["enum"], indent)
nested_classes.extend(enum_lines)
return enum_name, imports, nested_classes
prop_type = prop_schema.get("type")
if prop_type == "object":
class_name = capitalize(prop_name)
imports_inner, class_lines = generate_class(class_name, prop_schema, indent)
imports.update(imports_inner)
nested_classes.extend(class_lines)
return class_name, imports, nested_classes
elif prop_type == "array":
imports.add("java.util.List")
items = prop_schema.get("items", {})
item_type, imports_inner, nested_inner = get_java_type(prop_name + "Item", items, indent)
imports.update(imports_inner)
nested_classes.extend(nested_inner)
return f"List<{item_type}>", imports, nested_classes
else:
java_type = TYPE_MAPPING.get(prop_type, "Object")
return java_type, imports, nested_classes
def generate_enum(name, values, indent=1):
indent_str = " " * indent
lines = []
lines.append(f"{indent_str}public enum {name} " + "{")
enum_values = [v.upper().replace(" ", "_") for v in values]
lines.append(f"{indent_str} " + ", ".join(enum_values) + ";")
lines.append(f"{indent_str}}}\n")
return lines
def json_schema_to_pojo(schema_path, output_dir="generated", package="com.example", class_name="RootPojo"):
with open(schema_path) as f:
schema = json.load(f)
os.makedirs(output_dir, exist_ok=True)
imports, class_lines = generate_class(class_name, schema)
import_lines = []
if imports:
import_lines.append("import " + ";\nimport ".join(sorted(imports)) + ";")
import_lines.append("import com.fasterxml.jackson.annotation.JsonProperty;")
java_code = []
java_code.append(f"package {package};\n")
java_code.extend(import_lines)
java_code.append("\n")
java_code.extend(class_lines)
java_file_path = os.path.join(output_dir, f"{class_name}.java")
with open(java_file_path, "w") as f:
f.write("\n".join(java_code))
print(f"✅ Java POJO with validation and primary key generated at: {java_file_path}")
if __name__ == "__main__":
json_schema_to_pojo(
schema_path="Output_Schema.json",
output_dir="generated",
package="com.example.generated",
class_name="MyPojo"
)