JsonSerializer.java
package jsonserializer;
import models.Address;
import models.Company;
import models.Person;
import java.lang.reflect.Field;
public class JsonSerializer {
public static void main(String[] args) throws IllegalAccessException {
Company company = new Company("TechCorp", "Seattle", new Address("Pine Street", (short) 800));
Address address = new Address("Broadway", (short) 10);
Person person = new Person("Alice", true, 32, 1200.75f, address, company);
String jsonOutput = serializeToJson(person, 0);
System.out.println(jsonOutput);
}
public static String serializeToJson(Object obj, int indentLevel) throws IllegalAccessException {
Field[] fields = obj.getClass().getDeclaredFields();
StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.append(addIndentation(indentLevel)).append("{").append("\n");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
if (field.isSynthetic()) {
continue;
}
jsonBuilder.append(addIndentation(indentLevel + 1))
.append(formatString(field.getName()))
.append(": ");
if (field.getType().isPrimitive()) {
jsonBuilder.append(getPrimitiveValue(field, obj));
} else if (field.getType().equals(String.class)) {
jsonBuilder.append(formatString((String) field.get(obj)));
} else {
jsonBuilder.append(serializeToJson(field.get(obj), indentLevel + 1));
}
if (i < fields.length - 1) {
jsonBuilder.append(",");
}
jsonBuilder.append("\n");
}
jsonBuilder.append(addIndentation(indentLevel)).append("}");
return jsonBuilder.toString();
}
private static String addIndentation(int level) {
return "\t".repeat(level);
}
private static String getPrimitiveValue(Field field, Object obj) throws IllegalAccessException {
if (field.getType().equals(boolean.class) || field.getType().equals(int.class) || field.getType().equals(short.class)) {
return field.get(obj).toString();
} else if (field.getType().equals(float.class) || field.getType().equals(double.class)) {
return String.format("%.2f", field.get(obj));
}
throw new UnsupportedOperationException("Unsupported data type: " + field.getType().getName());
}
private static String formatString(String value) {
return "\"" + value + "\"";
}
}
models/Address.java
package models;
public class Address {
private final String street;
private final short apartment;
public Address(String street, short apartment) {
this.street = street;
this.apartment = apartment;
}
}
models/Company.java
package models;
public class Company {
private final String name;
private final String city;
private final Address address;
public Company(String name, String city, Address address) {
this.name = name;
this.city = city;
this.address = address;
}
}
models/Person.java
package models;
public class Person {
private final String name;
private final boolean employed;
private final int age;
private final float salary;
private final Address address;
private final Company job;
public Person(String name, boolean employed, int age, float salary, Address address, Company job) {
this.name = name;
this.employed = employed;
this.age = age;
this.salary = salary;
this.address = address;
this.job = job;
}
}
1. Class.getDeclaredFields()
- 설명: 해당 클래스에 선언된 모든 필드를 가져옵니다(접근 제한자와 관계없이).
- 사용 예:
Field[] fields = obj.getClass().getDeclaredFields();
2. Field.setAccessible(true)
- 설명: 필드가 private이나 protected로 선언된 경우에도 접근 가능하도록 설정합니다.
- 사용 예:
field.setAccessible(true);
3. Field.get(Object obj)
- 설명: 특정 객체에서 해당 필드의 값을 가져옵니다.
- 사용 예:
Object value = field.get(obj);
4. Field.getType()
- 설명: 필드의 데이터 타입(Class 객체)을 반환합니다.
- 사용 예:
if (field.getType().equals(String.class)) { // 문자열 처리 }
5. Field.isSynthetic()
- 설명: 컴파일러가 생성한 필드인지 확인합니다.
- 사용 예:
if (field.isSynthetic()) { continue; }
예제 코드 분석
JSON 직렬화 과정
- 필드 탐색 및 접근
- obj의 클래스에 선언된 모든 필드에 대해 Reflection을 사용해 값을 읽습니다.
Field[] fields = obj.getClass().getDeclaredFields(); field.setAccessible(true);
- obj의 클래스에 선언된 모든 필드에 대해 Reflection을 사용해 값을 읽습니다.
- 데이터 타입에 따른 처리
- 기본형(Primitive), 문자열(String), 복합 객체(Object)로 분기하여 JSON 직렬화 방식을 달리합니다.
if (field.getType().isPrimitive()) { jsonBuilder.append(getPrimitiveValue(field, obj)); } else if (field.getType().equals(String.class)) { jsonBuilder.append(formatString((String) field.get(obj))); } else { jsonBuilder.append(serializeToJson(field.get(obj), indentLevel + 1)); }
- 기본형(Primitive), 문자열(String), 복합 객체(Object)로 분기하여 JSON 직렬화 방식을 달리합니다.
- 출력 예 Person 객체를 직렬화하면 다음과 같은 JSON 출력이 생성됩니다:
{ "name": "Alice", "employed": true, "age": 32, "salary": 1200.75, "address": { "street": "Broadway", "apartment": 10 }, "job": { "name": "TechCorp", "city": "Seattle", "address": { "street": "Pine Street", "apartment": 800 } } }