JSON to Java 클래스 생성기
JSON에서 Java POJO 클래스 생성
JSON 입력
Java 출력
JSON to Java 클래스 변환이란?
JSON to Java 클래스 변환은 원시 JSON 객체를 받아 private 필드, getter, setter가 포함된 POJO(Plain Old Java Object) 정의를 생성합니다. Java에는 내장된 JSON 타입 시스템이 없기 때문에, 모든 JSON API 응답, 설정 파일, 메시지 페이로드는 타입 안전한 방식으로 다루기 전에 대응하는 클래스가 필요합니다. Jackson과 Gson 같은 라이브러리는 리플렉션을 통해 JSON 키를 Java 필드에 매핑하지만, 클래스 정의가 먼저 존재해야 합니다.
JSON 역직렬화를 위한 표준 Java POJO는 각 JSON 키에 대한 private 필드, 인수 없는 생성자, 그리고 필드당 getter/setter 쌍을 선언합니다. 중첩된 JSON 객체는 별도의 클래스가 됩니다. 배열은 java.util.List 임포트와 함께 List<T> 필드가 됩니다. 원시 JSON 타입은 Java 기본 타입(int, double, boolean) 또는 제네릭 내부에서 사용될 때는 래퍼 타입(Integer, Double, Boolean)에 매핑됩니다. null 값은 일반적으로 Object 또는 nullable 참조 타입에 매핑됩니다.
이러한 클래스 정의를 수동으로 작성하는 것은 반복적인 작업입니다. 각 JSON 키를 읽고, 값에서 Java 타입을 판별하고, camelCase JSON에서 camelCase Java 필드로 명명 규칙을 변환하고, 중첩 객체에 대한 PascalCase 클래스 이름을 만들고, getter/setter 보일러플레이트를 추가해야 합니다. 15개 필드와 3개의 중첩 객체가 있는 JSON 객체라면 4개의 클래스, 30개 이상의 메서드를 작성하고 일관성을 유지해야 합니다. 변환기는 이 작업을 수 밀리초 안에 처리합니다.
JSON to Java 변환기를 사용하는 이유
Java POJO를 JSON에서 수동으로 생성하려면 각 필드를 직접 확인하고, 샘플 값에서 타입을 추론하고, getter/setter 쌍을 작성하고, 중첩 객체마다 이 과정을 반복해야 합니다. API 계약이 변경되면 모든 것을 수동으로 업데이트해야 합니다. 변환기는 이러한 기계적인 작업을 제거합니다.
JSON to Java 활용 사례
JSON to Java 타입 매핑
모든 JSON 값은 특정 Java 타입에 매핑됩니다. 아래 표는 변환기가 각 JSON 타입을 Java 동등 타입으로 어떻게 변환하는지 보여줍니다. 대안(Alternative) 열은 List<T> 같은 제네릭 컨텍스트에서 사용되는 래퍼 타입이나 Records 같은 최신 Java 기능을 보여줍니다.
| JSON 타입 | 예시 | Java 타입 | 대안 |
|---|---|---|---|
| string | "hello" | String | String |
| number (integer) | 42 | int | int / Integer |
| number (float) | 3.14 | double | double / Double |
| boolean | true | boolean | boolean / Boolean |
| null | null | Object | Object (or @Nullable String) |
| object | {"k": "v"} | NestedClass | Record (Java 16+) |
| array of strings | ["a", "b"] | List<String> | List<String> |
| array of objects | [{"id": 1}] | List<Item> | List<Item> |
| mixed array | [1, "a"] | List<Object> | List<Object> |
Java JSON 어노테이션 참조
Jackson 또는 Gson으로 JSON을 역직렬화할 때, 어노테이션은 JSON 키가 Java 필드에 어떻게 매핑되는지, 알 수 없는 필드를 어떻게 처리하는지, null 값을 어떻게 다루는지를 제어합니다. 이 참조는 생성된 POJO로 작업할 때 가장 자주 접하는 어노테이션을 다룹니다.
| 어노테이션 | 용도 | 라이브러리 |
|---|---|---|
| @JsonProperty("name") | Maps a JSON key to a Java field with a different name | Jackson |
| @SerializedName("name") | Same as @JsonProperty, but for the Gson library | Gson |
| @JsonIgnoreProperties | Ignores unknown JSON keys during deserialization instead of failing | Jackson |
| @Nullable | Marks a field as accepting null values from JSON input | JSR 305 / JetBrains |
| @NotNull | Enforces that a field must not be null, throws on violation | Bean Validation |
| @JsonFormat(pattern=...) | Defines a date/time format for serialization and deserialization | Jackson |
POJO vs Record vs Lombok
Java에는 JSON 데이터를 담기 위한 타입이 지정된 구조를 정의하는 세 가지 일반적인 방법이 있습니다. 각각 다른 프로젝트 스타일과 Java 버전에 적합합니다. POJO는 가장 넓은 호환성을 가진 전통적인 패턴입니다. Record는 불변 데이터의 보일러플레이트를 줄입니다. Lombok은 어노테이션을 통해 컴파일 시점에 getter, setter, 생성자를 생성합니다.
코드 예제
이 예제들은 역직렬화를 위해 Jackson과 함께 생성된 Java POJO를 사용하는 방법, JavaScript와 Python에서 프로그래밍 방식으로 Java 클래스를 생성하는 방법, 그리고 일괄 생성을 위한 jsonschema2pojo CLI 도구 사용법을 보여줍니다.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private int id;
private String name;
private String email;
private boolean active;
private double score;
private Address address;
private List<String> tags;
// getters and setters omitted for brevity
public static void main(String[] args) throws Exception {
String json = "{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@example.com\",\"active\":true,\"score\":98.5,\"address\":{\"street\":\"123 Main St\",\"city\":\"Springfield\",\"zip\":\"12345\"},\"tags\":[\"admin\",\"user\"]}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println(user.getName()); // -> Alice
}
}
class Address {
private String street;
private String city;
private String zip;
// getters and setters
}// Minimal JSON-to-Java-POJO generator in JS
function jsonToJava(obj, name = "Root") {
const classes = [];
function infer(val, fieldName) {
if (val === null) return "Object";
if (typeof val === "string") return "String";
if (typeof val === "number") return Number.isInteger(val) ? "int" : "double";
if (typeof val === "boolean") return "boolean";
if (Array.isArray(val)) {
const first = val.find(v => v !== null);
if (!first) return "List<Object>";
const elem = infer(first, fieldName);
const boxed = elem === "int" ? "Integer" : elem === "double" ? "Double" : elem === "boolean" ? "Boolean" : elem;
return `List<${boxed}>`;
}
if (typeof val === "object") {
const cls = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
build(val, cls);
return cls;
}
return "Object";
}
function build(obj, cls) {
const fields = Object.entries(obj).map(([k, v]) => {
const type = infer(v, k);
return ` private ${type} ${k};`;
});
classes.push(`public class ${cls} {\n${fields.join("\n")}\n}`);
}
build(obj, name);
return classes.join("\n\n");
}
console.log(jsonToJava({ id: 1, name: "Alice", scores: [98, 85] }, "User"));
// public class User {
// private int id;
// private String name;
// private List<Integer> scores;
// }import json
def json_to_java(obj: dict, class_name: str = "Root") -> str:
classes = []
def infer(val, name):
if val is None:
return "Object"
if isinstance(val, bool):
return "boolean"
if isinstance(val, int):
return "int"
if isinstance(val, float):
return "double"
if isinstance(val, str):
return "String"
if isinstance(val, list):
if not val:
return "List<Object>"
elem = infer(val[0], name)
boxed = {"int": "Integer", "double": "Double", "boolean": "Boolean"}.get(elem, elem)
return f"List<{boxed}>"
if isinstance(val, dict):
cls = name[0].upper() + name[1:]
build(val, cls)
return cls
return "Object"
def build(obj, cls):
fields = [f" private {infer(v, k)} {k};" for k, v in obj.items()]
classes.append(f"public class {cls} {{\n" + "\n".join(fields) + "\n}")
build(obj, class_name)
return "\n\n".join(classes)
data = json.loads('{"id": 1, "name": "Alice", "tags": ["admin"]}')
print(json_to_java(data, "User"))
# public class User {
# private int id;
# private String name;
# private List<String> tags;
# }# Install jsonschema2pojo (requires Java 8+)
# Download from https://github.com/joelittlejohn/jsonschema2pojo
# Generate POJOs from a JSON file
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style jackson2
# Generate with Gson annotations instead
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style gson
# From a JSON string via stdin
echo '{"id": 1, "name": "Alice", "tags": ["admin"]}' | \
jsonschema2pojo --source-type json --annotation-style jackson2 \
--target src/main/java --target-package com.example.model