JSON → Java 클래스 변환기
JSON에서 getter와 setter를 갖춘 Java 클래스를 생성하고, Jackson 기반 Converter도 함께 제공합니다.
JSON에서 Java POJO 생성
Java에서 JSON을 매핑하려면 보통 객체마다 private 필드, getter, setter, 어노테이션을 갖춘 POJO를 작성해야 합니다. 이 변환기는 샘플에서 이를 생성해 줍니다. 각 객체는 접근자에 Jackson @JsonProperty 어노테이션이 붙은 클래스가 되고, 중첩 객체는 별도의 클래스가 되며, 배열은 타입이 지정된 배열, 정수는 long이 됩니다. fromJsonString과 toJsonString 메서드를 가진 Converter 클래스가 날짜·시간 파싱 헬퍼를 포함한 Jackson ObjectMapper 설정을 감싸 줍니다.
사용 방법
- Spring이나 Android 앱이 사용하는 REST 응답 같은 JSON 샘플을 붙여넣습니다.
- 루트 클래스 이름을 입력합니다. 예: Customer.
- Maven 또는 Gradle 빌드에 jackson-databind를 추가하고, 각 클래스를 패키지 안의 개별 .java 파일로 옮긴 뒤 Converter.fromJsonString(json)을 호출합니다.
자주 묻는 질문
- 출력이 왜 이렇게 긴가요?
- Java는 필드, getter, setter를 명시적으로 작성해야 하고, 생성된 Converter에는 java.time API용 날짜·시간 헬퍼가 포함되어 있기 때문입니다. 모델만 필요하다면 데이터 클래스만 복사하고 기존 ObjectMapper를 사용하세요.
- Java record나 Lombok을 대신 사용할 수 있나요?
- 생성기는 호환성을 최대한 확보하기 위해 전통적인 클래스를 작성합니다. 복사한 뒤 record(Java 16 이상)로 바꾸거나 Lombok의 @Data를 붙여도 되며, Jackson은 두 방식 모두 지원합니다.
- Spring Boot에서 사용할 수 있나요?
- 네. Spring Boot는 기본적으로 Jackson을 사용하므로, 어노테이션이 붙은 클래스를 Converter 클래스 없이 @RequestBody나 응답 타입으로 바로 사용할 수 있습니다.
예시: JSON to Java
입력 JSON
{
"customerId": 501,
"fullName": "Grace Hopper",
"vip": true,
"addresses": [{ "city": "Arlington", "zip": "22201" }]
}생성된 Java 코드 (Customer)
// Converter.java
// To use this code, add the following Maven dependency to your project:
//
//
// com.fasterxml.jackson.core : jackson-databind : 2.9.0
// com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0
//
// Import this package:
//
// import io.quicktype.Converter;
//
// Then you can deserialize a JSON string with
//
// Customer data = Converter.fromJsonString(jsonString);
package io.quicktype;
import java.io.IOException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.*;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
public class Converter {
// Date-time helpers
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_INSTANT)
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
.toFormatter()
.withZone(ZoneOffset.UTC);
public static OffsetDateTime parseDateTimeString(String str) {
return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();
}
private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_TIME)
.appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)
.parseDefaulting(ChronoField.YEAR, 2020)
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.toFormatter()
.withZone(ZoneOffset.UTC);
public static OffsetTime parseTimeString(String str) {
return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();
}
// Serialize/deserialize helpers
public static Customer fromJsonString(String json) throws IOException {
return getObjectReader().readValue(json);
}
public static String toJsonString(Customer obj) throws JsonProcessingException {
return getObjectWriter().writeValueAsString(obj);
}
private static ObjectReader reader;
private static ObjectWriter writer;
private static void instantiateMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
SimpleModule module = new SimpleModule();
module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
@Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value = jsonParser.getText();
return Converter.parseDateTimeString(value);
}
});
mapper.registerModule(module);
reader = mapper.readerFor(Customer.class);
writer = mapper.writerFor(Customer.class);
}
private static ObjectReader getObjectReader() {
if (reader == null) instantiateMapper();
return reader;
}
private static ObjectWriter getObjectWriter() {
if (writer == null) instantiateMapper();
return writer;
}
}
// Customer.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Customer {
private long customerID;
private String fullName;
private boolean vip;
private Address[] addresses;
@JsonProperty("customerId")
public long getCustomerID() { return customerID; }
@JsonProperty("customerId")
public void setCustomerID(long value) { this.customerID = value; }
@JsonProperty("fullName")
public String getFullName() { return fullName; }
@JsonProperty("fullName")
public void setFullName(String value) { this.fullName = value; }
@JsonProperty("vip")
public boolean getVip() { return vip; }
@JsonProperty("vip")
public void setVip(boolean value) { this.vip = value; }
@JsonProperty("addresses")
public Address[] getAddresses() { return addresses; }
@JsonProperty("addresses")
public void setAddresses(Address[] value) { this.addresses = value; }
}
// Address.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Address {
private String city;
private String zip;
@JsonProperty("city")
public String getCity() { return city; }
@JsonProperty("city")
public void setCity(String value) { this.city = value; }
@JsonProperty("zip")
public String getZip() { return zip; }
@JsonProperty("zip")
public void setZip(String value) { this.zip = value; }
}