IT/Live Coding

RoboPOJOGenerator로 외부 API JSON 쉽게 자바 객체로 변환하기 (테스트 영상 & 소스코드 포함)

어흥꼬비 2025. 4. 7.

RoboPOJOGenerator로 외부 API JSON 쉽게 자바 객체로 변환하기 (테스트 영상 & 소스코드 포함)

이번 포스팅에서는 Spring Boot 환경에서 RoboPOJOGenerator 플러그인을 활용해, 외부 API의 JSON 응답을 Java 객체로 간편하게 매핑하는 방법을 소개합니다.
이번에도 작게 만들며 키워가는 small make 방식으로 구현해보았습니다.

이거 수동으로 만들려면 은근히 시간 걸립니다.

편의상 직접 외부 API 호출하지 않고 JSON 문자열로 파싱 했습니다.


동영상 🎬

소스 💻

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.10'
    id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.test.lsy'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

dto

package com.test.lsy.tmpjson2java250407.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

@Data
public class Response{
	@JsonProperty("per_page")
	private int perPage;
	private int total;
	private List<DataItem> data;
	private int page;
	@JsonProperty("total_pages")
	private int totalPages;
	private Support support;
}
package com.test.lsy.tmpjson2java250407.dto;

import lombok.Data;

@Data
public class Support{
	private String text;
	private String url;
}
package com.test.lsy.tmpjson2java250407.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class DataItem{
	@JsonProperty("last_name")
	private String lastName;
	private int id;
	private String avatar;
	@JsonProperty("first_name")
	private String firstName;
	private String email;
}

service

package com.test.lsy.tmpjson2java250407.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.lsy.tmpjson2java250407.dto.Response;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@RequiredArgsConstructor
public class ApiService {
	
    // java 15이상부터 지원하는 문법 """ 문자열 """
    private final String jsonStr = """
{
  "page": 1,
  "per_page": 6,
  "total": 12,
  "total_pages": 2,
  "data": [
    {
      "id": 1,
      "email": "george.bluth@reqres.in",
      "first_name": "George",
      "last_name": "Bluth",
      "avatar": "https://reqres.in/img/faces/1-image.jpg"
    },
    {
      "id": 2,
      "email": "janet.weaver@reqres.in",
      "first_name": "Janet",
      "last_name": "Weaver",
      "avatar": "https://reqres.in/img/faces/2-image.jpg"
    },
    {
      "id": 3,
      "email": "emma.wong@reqres.in",
      "first_name": "Emma",
      "last_name": "Wong",
      "avatar": "https://reqres.in/img/faces/3-image.jpg"
    },
    {
      "id": 4,
      "email": "eve.holt@reqres.in",
      "first_name": "Eve",
      "last_name": "Holt",
      "avatar": "https://reqres.in/img/faces/4-image.jpg"
    },
    {
      "id": 5,
      "email": "charles.morris@reqres.in",
      "first_name": "Charles",
      "last_name": "Morris",
      "avatar": "https://reqres.in/img/faces/5-image.jpg"
    },
    {
      "id": 6,
      "email": "tracey.ramos@reqres.in",
      "first_name": "Tracey",
      "last_name": "Ramos",
      "avatar": "https://reqres.in/img/faces/6-image.jpg"
    }
  ],
  "support": {
    "url": "https://contentcaddy.io?utm_source=reqres&utm_medium=json&utm_campaign=referral",
    "text": "Tired of writing endless social media content? Let Content Caddy generate it for you."
  }
}
""";

    private final ObjectMapper om;

    public Response get() throws JsonProcessingException {
        return om.readValue(jsonStr, Response.class);
    }
}

ObjectMapper

package com.test.lsy.tmpjson2java250407.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ObjectMapperConfig {

    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }
}

controller

package com.test.lsy.tmpjson2java250407.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.test.lsy.tmpjson2java250407.dto.Response;
import com.test.lsy.tmpjson2java250407.service.ApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@RequiredArgsConstructor
public class ApiController {

    private final ApiService service;

    @GetMapping("/call")
    public Response get() throws JsonProcessingException {
        return service.get();
    }
}

응답 구조의 순서랑 타입이 일부 안 맞는 점 등 100% 완벽하게 java로 변환해주지는 못하지만 시간이 많이 단축된다.


개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.

틀린 점 있을 경우 댓글 부탁드립니다.

 

Spring Boot + Jasypt를 이용한 암호화 테스트 🔐 (테스트 영상 & 소스코드 포함)

Spring Boot와 Jasypt를 이용한 간단한 암호화 예제입니다.애플리케이션 설정 파일에 포함된 민감한 정보를 암호화해서 안전하게 관리하는 방법을 다뤄봅니다.이 예제에서는 Spring Boot와 Jasypt를 활용...

yaga.tistory.com

 

Spring Cloud Gateway + API 서버 연동 예제 🚀 (테스트 영상 & 소스코드 포함)

Spring Boot에서 Spring Cloud Gateway를 활용해 API 서버와 연동하는 간단한 예제입니다.이번에도 small make 방식으로 구현했습니다.이 예제에서는 Gateway 서버가 클라이언트의 요청을 받아 특정 경로에 따...

yaga.tistory.com

 

Spring Boot + Redis로 세션 공유하기 (테스트 영상 & 소스 코드 포함)

Redis를 활용한 애플리케이션 간 세션 공유 실험! (짧고 간단한 영상)레디스를 공부한지 얼마 안되어서 까먹기 싫어 기록으로 남긴다.동영상소스application.ymlserver: port: 9090 servlet: context-path: / encodin...

yaga.tistory.com

댓글