today_is

[ json ] HashMap 을 이용한 json 데이터 mapping 본문

spring

[ json ] HashMap 을 이용한 json 데이터 mapping

ye_rang 2024. 2. 4. 17:31

오늘의 목표 

공공데이터 포털에 있는 json 데이터를 HashMap 으로 mapping 해서 출력해보자 

 


 프로젝트 구조 

 

 

 

 home.jsp 

: 시작 페이지, a 태그를 이용하여 페이지 이동

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>day09</h1>
<hr>

<h3>JSON : JavaScript Object Notation</h3>
<h3>자바스크립트에서 객체를 표현하는데 사용하는 문법</h3>

<ul>
	<li><a href="ex01">ex01 - 부산 축제 정보 서비스 연습</a></li>
	<li><a href="ex02">ex02 - 부산 축제 정보 서비스 (AJAX)</a></li>
</ul>


</body>
</html>

 

 

 ex01.jsp 

:  json 파일을 자바 객체로 변환하여 출력하기 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="cpath" value="${pageContext.request.contextPath }" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ex01.jsp</title>
<style>
	#root {
		width: 900px;
		margin: 20px auto;
	}
	.item {
		width: 800px;
		margin: 10px auto;
		border: 1px solid grey;
		padding: 10px;
	}
</style>
</head>
<body>

<h1>ex01 - JSON을 자바 객체로 변환하여 출력하기</h1>
<hr>

<p>
	<a href="${cpath }/ex01/js"><button>JS로 처리하기</button></a>
</p>

<div id="root">
	<c:forEach var="dto" items="${list }">
	<div class="item">
		<div><h3>${dto.UC_SEQ }. ${dto.TITLE } (${dto.GUGUN_NM })</h3></div>
		<div>${dto.HOMEPAGE_URL }</div>
		<div><img src="${dto.MAIN_IMG_NORMAL }" height="300"></div>
		<div>
			<details>
				<summary>상세보기</summary>
				<span>${dto.ITEMCNTNTS }</span>
			</details>
		</div>
	</div>
	</c:forEach>
</div>


</body>
</html>

 

해당 API 의 내용을 알아야함.

필드명이 일치해야 불러올 수 있기 때문

 

 

 ex01- js.jsp 

: json 파일을 자바 스크립트로 변환하여 출력하기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ex01-js</title>
<style>
	#root {
		width: 900px;
		margin: 20px auto;
	}
	.item {
		width: 800px;
		margin: 10px auto;
		border: 1px solid grey;
		padding: 10px;
	}
</style>
</head>
<body>

<h1>ex01 - JSON을 자바스크립트로 처리하여 출력하기</h1>
<hr>

<div id="root"></div>

<script>
	const jsonObject = ${json}
	
// 	console.log(jsonObject.getFestivalKr.item)
	const arr = jsonObject.getFestivalKr.item
	const root = document.getElementById('root')
	
	root.innerHTML = ''
	for(let i = 0; i < arr.length; i++) {
		let tag = ''
		tag += '<div class="item">'
		tag += '	<div><h3>' + arr[i].UC_SEQ + '. ' + arr[i].TITLE + '(' + arr[i].GUGUN_NM + ')</h3></div>'
		tag += '	<div>' + arr[i].HOMEPAGE_URL + '</div>'
		tag += '	<div><img src="' + arr[i].MAIN_IMG_NORMAL + '" height="300"></div>'
		tag += '	<div>'
		tag += '		<details>'
		tag += '			<summary>상세보기</summary>'
		tag += '			<span>' + arr[i].ITEMCNTNTS + '</span>'
		tag += '		</details>'
		tag += '	</div>'
		tag += '</div>'
		root.innerHTML += tag
	}
</script>

</body>
</html>

 

 

 Ex01Controller 

package com.itbank.controller;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itbank.service.Ex01Service;

@Controller
public class Ex01Controller {
	
	@Autowired private Ex01Service service;
	private ObjectMapper objectMapper = new ObjectMapper();
	
	@GetMapping("/ex01/js")
	public ModelAndView ex01Js() throws MalformedURLException, IOException {
		ModelAndView mav = ex01();
		mav.setViewName("ex01-js");
		return mav;
	}

	@GetMapping("/ex01")
	public ModelAndView ex01() throws MalformedURLException, IOException {
		ModelAndView mav = new ModelAndView();
		
		String json = service.getFestivalJson();	// JSON 데이터는 문자열이다
		mav.addObject("json", json);
		System.out.println(json);
		
		// JSON 형식의 문자열을 자바 객체로 변환하기 위한 코드
		JsonNode node = objectMapper.readTree(json);
		JsonNode item = node.get("getFestivalKr").get("item");
		System.out.println("item : " + item.toPrettyString());
		
//		DTO로 맵핑하기 (필드이름이 복잡하여 제대로 맵핑되지 않았다)
//		List<FestivalDTO> list = Arrays.asList(
//				objectMapper.readValue(item.toPrettyString(), FestivalDTO[].class)
//		);
//		System.out.println(list.get(0).getMAIN_TITLE());
		
//		HashMap으로 맵핑하기
		@SuppressWarnings("unchecked")
		List<HashMap<String, Object>> list = Arrays.asList(
				objectMapper.readValue(item.toPrettyString(), HashMap[].class)
		);
		System.out.println(list.get(0).get("MAIN_TITLE"));
		
		mav.addObject("list", list);
		return mav;
	}
}

 

 Ex01Controller  내용 중 어려웠던 부분 

처음에는 DTO 로 처리하려고 했으나, 필드명이 복잡했기 때문에 mapping 이 잘 되지 않았음

 

수정사안 ) mapping 을 HashMap 으로 구현 

 

 

 

(+) FestivalDTO 

package com.itbank.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

// JSON데이터에서 DTO에 명시되지 않은 속성(알수없는 속성)은 무시하겠다
@JsonIgnoreProperties(ignoreUnknown = true)

// JSON의 속성이름을 자바 네이밍 컨벤션(camelCase)으로 변환하는 과정이 맞아야 한다
public class FestivalDTO {

	@JsonProperty("UC_SEQ")				private int UC_SEQ;
	@JsonProperty("MAIN_TITLE")			private String MAIN_TITLE;
	@JsonProperty("GUGUN_NM")			private String GUGUN_NM;
	@JsonProperty("HOMEPAGE_URL")		private String HOMEPAGE_URL;
	@JsonProperty("MAIN_IMG_NORMAL")	private String MAIN_IMG_NORMAL;
	@JsonProperty("ITEMCNTNTS")			private String ITEMCNTNTS;
	
	public int getUC_SEQ() {
		return UC_SEQ;
	}
	public void setUC_SEQ(int uC_SEQ) {
		UC_SEQ = uC_SEQ;
	}
	public String getMAIN_TITLE() {
		return MAIN_TITLE;
	}
	public void setMAIN_TITLE(String mAIN_TITLE) {
		MAIN_TITLE = mAIN_TITLE;
	}
	public String getGUGUN_NM() {
		return GUGUN_NM;
	}
	public void setGUGUN_NM(String gUGUN_NM) {
		GUGUN_NM = gUGUN_NM;
	}
	public String getHOMEPAGE_URL() {
		return HOMEPAGE_URL;
	}
	public void setHOMEPAGE_URL(String hOMEPAGE_URL) {
		HOMEPAGE_URL = hOMEPAGE_URL;
	}
	public String getMAIN_IMG_NORMAL() {
		return MAIN_IMG_NORMAL;
	}
	public void setMAIN_IMG_NORMAL(String mAIN_IMG_NORMAL) {
		MAIN_IMG_NORMAL = mAIN_IMG_NORMAL;
	}
	public String getITEMCNTNTS() {
		return ITEMCNTNTS;
	}
	public void setITEMCNTNTS(String iTEMCNTNTS) {
		ITEMCNTNTS = iTEMCNTNTS;
	}
	

}

 

 

 Ex01Service 

: Ex01Controller의 호출을 받고

요청된 내용을 처리한 후

결과값을 호출한 장소로 반환한다 

package com.itbank.service;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Scanner;

import org.springframework.stereotype.Service;

@Service
public class Ex01Service {
	// 공공데이터포털, 부산 축제 정보

	private final String serviceKey = "K7G5hCA%2FRqnmALDK%2F7POZXDGSgTgQFRIcOqpF8HUf9rqLn17QSaJ4Q0Ox732h%2BF%2FgxuyB3bXrdEWApNVwrOtWA%3D%3D";
	
	public String getFestivalJson() throws MalformedURLException, IOException {
		// 1) 요청 주소 및 파라미터 준비
		String url = "https://apis.data.go.kr/6260000/FestivalService/getFestivalKr";
		HashMap<String, String> param = new HashMap<>();
		param.put("pageNo", "1");
		param.put("numOfRows", "10");
		param.put("resultType", "json");
		param.put("serviceKey", serviceKey);
		url += "?";
		for(String key : param.keySet()) {
			url += key + "=" + param.get(key) + "&";
		}
		
		// 2) 요청을 전송하여 응답을 받아서 저장
		Scanner sc = null;
		String response = "";
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		
		if(conn.getResponseCode() == 200) {	// 200 = 정상
			sc = new Scanner(conn.getInputStream());
			while(sc.hasNextLine()) {
				response += sc.nextLine();
			}
			sc.close();
			conn.disconnect();
		}
		
		return response;
	}

}

 

 Ex01Service 주의할 점 

공공데이터포털 사이트에서 url 과 serviceKey 오타를 조심하자.

 


Study_review

 

처음에는 DTO로 매핑하려고 계속 코드를 수정했으나, 비효율적인 코드가 되었다.

이를 해결하고자 챗지피티에게 물어보았고, HashMap을 이용하게 되었다.

DTO를 이용해도 충분히 답을 얻을 수 있었겠지만, 일일이 코드를 수정해야 하는 상황이라

현재의 로직으로 바꾼 것이 신의 한 수였던 것 같다.

 

 

나의 원칙 = 비효율적인 방식은 선택하지말자.

'spring' 카테고리의 다른 글

[ websocket ] 메모장  (0) 2024.03.03
[ spring ] 다른 ip와 DB 내용 공유하기  (0) 2024.03.03
[ Exception ] 예외처리, 예외전가  (0) 2024.01.30
[ spring ] 간단한 POS 구현  (0) 2024.01.19
[ spring ] RestController  (0) 2024.01.16