본문 바로가기
백엔드/웹 개발

JSON 데이터 다루기(내장객체, 라이브러리)

by study_yeon 2023. 8. 21.

2023.08.16 ~ 8.17 수업

 

◎ JSON을 배우기 전 짚고 넘어가기

더보기

REST API로 요청을 보내고 응답을 받으면 JSON 형태로 데이터를 가져온다

REST API란 쉽게 말해서 자원의 이름으로 자원의 상태를 주고받을 수 있는 API이다.
JSON 이나 XML 을 사용해서 데이터(자원)를 주고받는 것이 일반적이다.

 

RESTful 웹 서비스는 XML 대신 JSON 데이터를 사용하고 생성한다. 
Java SE는 JSON을 자바객체로(또는 그 반대로) 변환하는 것을 지원하지 않는다. 
그래서 라이브러리를 사용해야한다

 

Jackson 과 Gson 라이브러리를 주로 사용한다 

- 두 개의 라이브러리는 JSON data-binding(JSON 데이터 ↔ Java 객체로 직렬화 & 역직렬화) 지원 라이브러리

- JSON 파싱시 자주 쓰이는 라이브러리


● 데이터를 서버에서 수신할 때 사용되는 형식

1. JSON(JavaScript Object Nation)
자바스크립트에서 객체 표기법으로 데이터 전달
키명을 다 적어야하므로 데이터의 양이 많아 속도가 느려짐

네트워크를 통해 데이터를 주고받는 데 자주 사용되는 경량의 데이터 형식

2. XML(eXtensible Markup Language)
HTML형식처럼 태그로 데이터 표현
HTML태그처럼 미리 지정되어 있지 않고 사용자가 직접 정의
용량을 많이 차지함
<태그>값

3. CVS(Comma Separated Values)
각 항목을 쉼표로 구분해서 데이터 표현
용량은 적고 많은 데이터를 처리하지만 데이터가 무엇을 의미하는지 알기 어렵다
값1, 값2, 값3...


◎ JSON(JavaScript Object Nation)

- 자바스크립트에서 객체 표기법을 나타내는 것
- 경량데이터 교환 형식
- 웹 서버와 데이터를 교환하기 위해 사용
- 데이터 저장 및 전송 용도로 사용하는 텍스트 형식의 데이터

- 네트워크를 통해 서로 다른 시스템들이 데이터를 주고 받을 때 많이 사용(가독성이 좋음) 
- 문자열(" ")
- JSON은 {"키": 값} - 키 명에 큰 따옴표 표시
- js는 {키: 값}

- 값은 배열, 또는 객체가 가능 : 객체는 {} 로, 배열은 []로 사용된다

▷ JSON 데이터 유형
- 문자열 : 값은 큰 따옴표로 묶기
- 숫자 : 정수 또는 부동 소수점
- 객체 : JSON 값
- 배열 : JSON 값
- true/false : Boolean
- null : 키워드(null) 사용

※ 날짜 객체는 JSON에서 허용되지 않음
날짜를 문자열로 작성 후 자바스크립트에서 다시 'new Date()'를 통해 생성
json문자열 데이터 객체로 만드는 것


◎ 자바스크립트로 JSON 데이터 다루기

 

▶ JSON 내장 객체

- JavaScript 객체와 JSON 문자열 간의 상호 변환을 수행해주는 메서드 제공

- JSON.parse() / JSON.stringify()

- 전역에서 접근 가능 

 

* js객체의 타입 : object(객체)
* json데이터의 타입 : string(문자열)

 

▷ JSON.parse()

- 웹 서버에서 데이터를 수신할 때 데이터는 "문자열" 형태이기 때문에,

 JSON데이터로 가져와서 parse()를 통해 바스크립트 객체로 변경이 필요 
- json문자열을 js객체(Object)로 만드는 기능(문자열을 자바스크립트 오브젝트로 변경)

- 자바스크립트 객체로 데이터가 바뀐다

- 각각의 문서 객체에 텍스트 콘텐츠로 데이터 속성을 호출해서 추가

- data를 분석할때 사용

 

* JSON데이터를 JS객체로 변경하기 

<script>
	const originData = '{"name" : "진", "age" : 32 , "birth" : 1998 }';
	const changeData = JSON.parse(originData);
    
    alert(typeof(changeData));
</script>

-> 자바스크립트 객체로 변경됨


JSON.stringify()

- JSON의 일반적인 사용용도는 웹서버와 데이터를 교환하는 것이다.
- 웹 서버에 데이터를 보낼 때 데이터는 문자열이어야 한다

- 자바스크립트 객체 데이터를 문자열로 변환
- js객체를 JSON데이터로 변경
- JSON은 대문자로 작성

* js객체를 JSON데이터로 변경하기

<script>
	const originData = {name : "진", age : 32 , birth : "1998-07-12" }; // JS객체 
	const changeData = JSON.stringify(originData);
    
    alert(changeData)
    alert(typeof(changeData));
</script>

alert(changeData)

-> JSON 데이터로 변경되어 키 값에 큰 따옴표가 생성됨

alert(typeof(changeData));

-> JSON 객체(문자열)로 변경됨


Web Storage API를 사용한 데이터 저장
- JSON을 사용하면 자바스크립트 개체를 텍스트로 저장할 수 있다

 

▷ 개념
※ API(Application Programming Interface)
- 라이브러리에 접근하기 위한 규칙을 정의한 것
- 내부구조를 알 필요 없이 단순히 API에 정의된 입력 값을 주고 결과 값을 사용할 수 있음 
- 점원과 유사한 역할, 매개체

※ Web Storage API
- 브라우저에서 데이터를 저장하고 검색하기 위한 간단한 구문
- 서버(데이터베이스나 클라우드)에 저장할 필요가 없을 때 사용
- 크기가 작은 쿠키를 대체하기 위한 자바스크립트의 하드디스크 파일
- 기본적으로 키(key)와 값(value)으로 이루어진 데이터를 저장
-  로컬 스토리지(localStorage)와 세션 스토리지(sessionStorage)로 나뉨
- 세션 스토리지는 웹페이지의 세션이 끝날 때 저장된 데이터가 지워지고,
로컬 스토리지는 웹페이지의 세션이 끝나더라도 데이터가 지워지지 않는다.

문자형(string) 데이터 타입만 지원

-> JSON 형태로 데이터를 읽고 쓰면 해결 

    객체나 배열를 저장하기 위해서는 객체를 문자열로 변환해서 저장해야 한다

    JSON.stringify() 함수를 사용하여 객체와 배열을 JSON 문자열로 변환
    스토리지에 쓸 데이터를 JSON형태로 직렬화(stringify)하고 읽은 데이터를 JSON형태로 역직렬화(parse) 

○ localStorage

- 보관 기한이 없는 데이터를 저장할 수 있는 객체

 

* Storage 메소드

- localStorage가 Storage 타입의 객체이기 때문에 Storage의 메소드를 호출하여 데이터를 관리
setItem(name, value) - key, value 저장
getItem(name) - value 읽어 오기, 검색
removeItem(name) - item 삭제
key(index) - index로 key값 찾기

clear() - 도메인 내의 localStorage 값 삭제
length - 전체 item 갯수, key-value 쌍의 갯수 

<script>
	// 데이터 저장
	const myObj = {name : "진"};
	const myJson = JSON.stringify(myObj);
	localStorage.setItem("testJSON", myJson);

	// 데이터 읽기
	let text = localStorage.getItem("testJSON");
	let obj = JSON.parse(text);
    
	alert(obj.name);
</script>

 sessionStorage

- 하나의 세션만을 위한 데이터를 저장
- 사용자가 브라우저 탭이나 창을 닫으면 객체에 저장된 데이터는 사라진다

 

▷ 예외

※ JSON에서 날짜 객체는 허용되지 않음 

* 사용법
- 날짜를 문자로 반환하기 : JSON.stringify()
- 자바스크립트는 날짜 객체 허용 : new Date() 사용 

<script>
	const originData = {name : "디데이", today : new Date() };
	const changeData = JSON.stringify(originData);
    
    alert(changeData)
</script>

-> 날짜 형식이 JSON(문자열)으로 변경되어 큰 따옴표로 표시됨


* 데이터 변환 시 함수는(키와 값) 모두 제거됨, 속성(값)만 JSON으로 변경 됨
- 문자열로 값을 변환하고 싶다면 미리 문자열로 변경
- 변환을 하면 함수로 되돌아가지 않는다

<script>
	const originData = {name : "진", age : function() {return 30;} };
	const changeData1 = JSON.stringify(originData);
    
    alert(changeData1)
    
    originData.age = originData.age.toString();
    const changeData2 = JSON.stringify(originData);
    
    alert(changeData2)
</script>

함수인 age는 키와 값 모두 제거
문자열로 변경 후 호출하면 출력됨


◎ 스프링부트로 JSON 다루기

▶ JSON 데이터 작성하는 법

1. 이스케이프 시퀀스(\) : 원시적 방법으로 권장하지 않음

-> 복잡하고 오타의 위험 존재

// 어노테이션은 클래스의 메타데이터라고하여 내부적으로 클래스이다
// 어노테이션과 같은 이름의 클래스 생성 불가
@RestController // 응답결과는 스트링(JSON or Text)
public class JSONRestController {
	@GetMapping("/info")
	// info라는 주소로 요청을 하면 projectInfo메서드를 호출해라
	public String projectInfo() {
		// 1. 이스케이프 시퀀스(\) : 원시적 방법으로 권장하지 않음
		return "{ \"project name\" : \"preword\", \"created date\" : \"2022-07-31\" }";
}

2. 템플릿 문자열 사용(자바 17ver ~) : 권장하지 않음
-> 오타의 위험 존재

@RestController 
public class JSONRestController {
	@GetMapping("/info")
	public String projectInfo() {
		// 2. 템플릿 문자열 사용(자바 17ver ~) : 권장하지 않음
		return """
				{
					"project name" : "preword",
					"created date" : "2022-07-31"
				}
				""";
	}
}

3. Jackson : 권장

@RestController
public class JSONRestController {
	// 3. Jackson
	@GetMapping("/infoJackson")
	public Object projectInfoJackson() {
		Project project = new Project();
		
		project.setProjectName("preword");
		project.setAuthor("홍길동"); 		
		// project.setAuthor(null); // @JsonInclude 적용 대상 
		project.setCreatedDate(new Date());
		
		return project;
	}
}

◎ JSON 라이브러리

- JSON 파싱시 자주 쓰이는 라이브러리

- Jackson / Gson 

 

▶ Jackson

- 어노테이션을 사용하여 클래스 변수를 자동으로 JSON형태로 변환

- JSON 데이터 구조를 처리해주는 라이브러리 

- Java Object를 JSON으로 변환하거나 JSON 문자열을 Java Object로 변환

 

* 필수 작업
- 컨트롤러 클래스에 @RestController 또는 클래스에 @Controller + 함수(메서드)에 @ResponseBody
- model 클래스에 getter / setter

 


※ JSON Property 주요 어노테이션

 

@JsonIgnore

- 필드 단위에서 json으로 직렬화, 역직렬화시 제외시킬 목적
- 반환 값에 포함하지 않음(제외되어 출력)

 

▷ 컨트롤러

	@GetMapping("/infoJackson")
	public Object projectInfoJackson() {
		Project project = new Project();
		
		project.setProjectName("preword");
		project.setAuthor("홍길동"); 		
		project.setCreatedDate(new Date());
		
		return project;
	}

▷ 모델 클래스(엔티티)

private String projectName;
private String author;
@JsonIgnore
private Date createdDate;

-> createdDate 는 출력되지 않음


@JsonInclude
- 클래스 위에 작성
- 반환 값 설정

- 자바 객체를 json 형식 데이터로 직렬화할때 옵션을 통해서 원하는 값만 포함

● ALWAYS : 모든 데이터 json 변환, 값에 상관 없이 출력
 NON_NULL : null인 데이터 제외(직렬화된 출력)
 NON_ABSENT : null 과 참조유형의 absent 값은 제외(Optional)
 NON_EMPTY : NULL 값이 아니고 빈 컬렉션, 맵이 아닌 경우 출력
 - null 과 참조유형의 absent 값과 maps이 isEmpty(), array length가 0, String length 0 인 데이터 제외
 NON_DEFAULT : 속성의 값이 해당 데이터 형식의 기본값과 다른 경우 출력
 - empty데이터와 기본형이 default와 date가 0인 것들을 제외

 

▷ 컨트롤러

	@GetMapping("/infoJackson")
	public Object projectInfoJackson() {
		Project project = new Project();
		
		project.setProjectName("preword");
		// project.setAuthor("홍길동"); 		
		project.setAuthor(null); // @JsonInclude 적용 대상 
		project.setCreatedDate(new Date());
		
		return project;
	}

▷ 모델 클래스(엔티티)

@JsonInclude = objectMapper.setSerializationInclusion();

 

@JsonInclude(JsonInclude.Include.NON_NULL) // null이 아닌 것만 return에 포함
public class Project {
	private String projectName;
	private String author;
	private Date createdDate;

}

-> null 값을 가진 author 필드는 출력되지 않는다 


@JsonProperty
- 클래스의 속성명에 별명을 정해줌

- 데이터 전송시, 객체를 JSON 형식으로 변환할 때 Key의 이름을 설정

 

▷ 컨트롤러

	@GetMapping("/infoJackson")
	public Object projectInfoJackson() {
		Project project = new Project();
		
		project.setProjectName("preword");
		project.setAuthor("홍길동"); 		
		// project.setAuthor(null); // @JsonInclude 적용 대상 
		project.setCreatedDate(new Date());
		
		return project;
	}

▷ 모델 클래스(엔티티)

 

public class Project {
	private String projectName;
	@JsonProperty(value = "project master")
	private String author;
	// @JsonIgnore
	private Date createdDate;

}

@JsonProperty 적용 전
@JsonProperty 적용 후

-> author 필드가 설정된 이름으로 출력 



@JsonFormat
- 날짜, 시간값을 직렬화할 때 형식 지정

- 어노테이션은 Jackson 라이브러리에서 제공하는 어노테이션으로 JSON 형식의 날짜, 시간값을 지정할 때 사용

- pattern : 날짜 형식을 지정
- timezone : 특정 국가나 지역의 현지 시간(local time)을 지정

 

▷ 컨트롤러

	@GetMapping("/infoJackson")
	public Object projectInfoJackson() {
		Project project = new Project();
		
		project.setProjectName("preword");
		project.setAuthor("홍길동"); 		
		// project.setAuthor(null); // @JsonInclude 적용 대상 
		project.setCreatedDate(new Date());
		
		return project;
	}

▷ 모델 클래스(엔티티)

 

public class Project {
	private String projectName;
	@JsonProperty(value = "project master")
	private String author;
	@JsonFormat(shape = JsonFormat.Shape.STRING, 
			pattern= "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
	private Date createdDate;

}

-> createdDate의 시간표현이 설정한 값으로 출력 


▶ Gson 

- class를 만들지 않고 직접 JSON을 만들어서 보냄

- JSON형식만 처리
- 가벼운 JSON 데이터를 처리할 때 성능이 좋다
- 스프링 프레임워크에 내장되어있지 않기 때문에 build.gradle에 추가

▷ build.gradle의 dependencies에 코드 추가
- mvn repository : Gson 검색하여 Gradle(Short)의 코드 복사

implementation 'com.google.code.gson:gson:2.10.1'

- 추가 후 gradle Refresh 하기

 

▷ 컨트롤러

- import 하기 

	@GetMapping("/infoGson")
	public String gsonJson() {
		// 1) JsonObject객체 생성(최상위 객체)
		JsonObject jo = new JsonObject();
		// 2) JSON 요소 추가(키, 값)
		jo.addProperty("projectName", "preword");
		jo.addProperty("author", "황진이");
		jo.addProperty("createdDate", new Date().toString());
		
		JsonArray ja = new JsonArray();
		for (int i = 0; i < 5; i++) {
			JsonObject jObj = new JsonObject();
			jObj.addProperty("prop" + i, i);
			
			ja.add(jObj);
		}
		jo.add("follower", ja);
		// 진짜 JSON문자열이 된다
		return jo.toString();
	}

 

* Gson은 자세히 배우지 않음 


▶ Jackson 과 Gson

- 두 개의 라이브러리는 JSON data-binding(JSON 데이터 ↔ Java 객체로 직렬화 & 역직렬화) 지원 라이브러리

▷ Jackson의 장점
- 모든 JAX-RS및 스프링프레임워크에 내장
- 광범위한 애너테이션 지원

- 고용량의 JSON데이터를 처리할 때 GSON보다 성능이 좋다

 Gson의 장점
- 간단한 경우 사용이 편리
- 자바 엔티티를 통하지 않아도 됨(역직렬화 등) 


★ 나의 의문점
1. 파싱이 뭐야 ?

* Parsing
- 언어학에서 parsing은 구문 분석이라고도하며 문장을 그것을 이루고 있는 구성 성분으로 분해하고 그들 사이의 위계 관계를 분석하여 문장의 구조를 결정하는 것
- 문장의 구조를 표현하는 한 방법
- 데이터를 조립해 원하는 데이터를 빼내는 프로그램을 하는것
- 특정문서(XML 따위)를 읽어 들여서 이를 다른 프로그램이나 서브루틴이 사용할 수 있는 내부 의  표현 방식으로 변환시켜 주는 것

쉽게 말해 웹페이지에서 원하는 데이터를 추출하여 가공하기 쉬운 상태로 바꾸는 것으로 데이터를 원하는 모양으로 만들어 낼 수 있다

(참고) Parser : 파서는 파싱을 하는 프로세서. 즉, 파서가 파싱 작업을 하는 것.


2. 이걸 왜 파싱해?

- JSON은 네트워크를 통해 데이터를 주고받는 데 자주 사용되는 경량의 데이터 형식이다 
- JSON형태로 온 데이터들을 파싱해주어야한다
- JSON형태로는 데이터들을 이용할 수 없기 때문 
-> 데이터를 이용하기 위해 값이 name이고 value가 진이라는 분석이 필요하다