[22일차] JSON

유태형·2022년 5월 25일
0

코드스테이츠

목록 보기
22/77

오늘의 목표

  1. JSON
  2. 재귀적으로 JSON 구현하기



내용

JSON

JSON 사용 이유

자바스크립트와 자바, 파이썬, C, C++등 다른 언어간 통신,즉 구성된 각각의 클라이언트와 서버간의 데이터 통신에서 자바스크립트의 데이터와 다른 프로그래밍언어에서의 데이터 처리가 다름으로, 이 차이를 통일시키기 위해 사용되는 것이 JSON입니다.
예를 들어 자바는 Integer, Double, Boolean, String, 배열, 객체,...등등 자바만의 데이터타입이 존재하는데에 반해 자바스크립트는 단순히 변수, 배열, 객체...등등 자바스크립트만의 데이터타입이 존재함으로 이를 문자열로 통일 시켜 전송하고, 문자열을 자기만의 데이터타입으로 변환하기위해 사용되는 약속된 규칙입니다.



JSON의 형식

데이터 타입을 문자열로 바꾸었다고 하여 무조건 JSON이 되는 것은 아닙니다.

"{"키1":null,"키2":true,"키3":"string","키4":30,"키5":[값1,값2,...],"키6":{
"키6-1":"string2","키6-2":[값1,값2,...],"키6-3":{키,값}}

등으로 JSON에는 null, Number(숫자), Boolean, String, Object, Array가 요소로 들어올 수 있습니다.
ArrayObject내부에는 또 다시 null, Number(숫자), Boolean, String, Object, Array가 요소로 들어올 수 있습니다.

주의해야 할점은
1. JSON은 계층적인 데이터 구조(예를 들면 배열안의 배열안의 배열안의 .....)를 허용한다는점
2. 무조건 : 쌍으로만 이루어 진다는 점
3. 문자열은 반드시 쌍따옴표""로 묶고 키,값사이에는 띄어쓰기가 없어야 합니다.



JSON의 과정

우리가 흔히 사용하는 객체, 배열, 컬렉션 등등 자바환경에서 사용할때 모든 데이터들이 수평적이지 않고 배열 변수나, 객체에 계층적인 구조로 이루어 져있습니다. 이것을 전송과 자바스크립트에서의 읽기를 위해 모두 한줄의 문자열로 압축시키는 것을 Serialization이라고 합니다. 반대로 한줄로 압축된 문자열을 다시 계층적인 구조로 복구시키는 것을 Deserialization이라고 합니다.

  • 자바 환경 -> Serialization -> JSON -> Deserialization -> 자바스크립트 환경
  • 자바스크립트 환경 -> Serialization -> JSON -> Deserialization -> 자바 환경

의 과정으로 자바자바스크립트 환경이 각각 JSON으로 변환시켜 데이터를 주고받는 과정을 거칩니다.




재귀적으로 JSON 구현하기

Jackson

Jackson라이브러리는 간편하게 자바환경의 데이터를 간편하게 JSON으로 Serialization시키고, 또 JSON을 간편하게 Deserialization시키는 클래스와 메서드를 제공합니다.

ObjectMapper클래스를 제공함으로써 해당클래스의 객체를 인스턴스화 하여 JSON변환을 손쉽게 사용할 수 있습니다.

  • ObjectMapper.writeValueAsString(Map) : (키,값)쌍의 Map을 문자열로 변환 시킵니다.
  • ObjectMapper.readValue(문자열,Map.class) : JSON을 (키,값)상의 Map으로 변환 시킵니다.

이외에도 readValue, WriteValue를 응용한 다양한 메서드들이 존재합니다.



재귀적 구현은 어느 부분을?

앞서 설펴보았듯이 JSON은 null, Number(숫자), Boolean, String, Object, Array가 요소로 들어올 수 있습니다. null, Number(숫자), Boolean, String은 단일값을 가지므로 재귀적으로 표현할 수 없습니다.
불특정한 다수의 값을 가질 수 있는 Object, Array 안에 존재하는 단일요소의 갯수만큼 재귀함수를 호출하여 구현할수 있을 것 같습니다.
또 JSON에서 Object키 : 값쌍으로 표현되므로 Map컬렉션으로 표현할 수 있습니다.



배열을 재귀적으로 구현

	//데이터의 타입이 배열일 경우
	if(data instanceof Object[]){
		//재귀함수 호출
      return "[" + objectRecursive(data) + "]";
    }

stringify(Object obj)는 데이터의 타입을 구분하여 문자열을 반환하는 메서드입니다.

 public String objectRecursive(Object data){
    if(((Object[]) data).length == 0) return ""; //빈배열 -> 빈 문자열
    if(((Object[]) data).length == 1) return stringify(((Object[])data)[0]); //['요소'] -> 재귀함수(['요소'])x , 재귀함수('요소')o
    Object[] head = Arrays.copyOfRange((Object[])data, 0, 1); //head : 1
    Object[] tail = Arrays.copyOfRange((Object[])data, 1, ((Object[]) data).length); //tail : n
    /*
     * [true, false, true, true]
     * [true] [false,true,true]
     * true [false][true,true]
     * true  false [true] [true]
     * true false true [true]
     * true false true true
     * */

    //head와 tail을 각각 문자열로
    return objectRecursive(head) + "," + objectRecursive(tail);
  }

피보나치를 응용하였습니다. 배열의 맨앞 요소만 따로 분리시켜 배열을 2개로 나누어 감소식을 구현하였고 빈 배열일땐 빈 문자열, 배열의 길이가 1일때 배열의 요소를 끄집어내어 해당 배열의 요소의 타입을 다시 분석하였습니다.



HashMap을 재귀적으로 구현

	//입력된 값이 HashMap일 경우
    if(data instanceof HashMap){
      return "{" + mapRecursive(data) + "}";
    }

stringify(Object obj)는 데이터의 타입을 구분하여 문자열을 반환하는 메서드입니다.

  public String mapRecursive(Object data){
    //빈 해시 = 빈 문자열
    if(((HashMap)data).isEmpty()) return "";
    //하나의 해시맵 = 키 : 값 문자열
    if(((HashMap)data).size()==1){
      Iterator<Object> iter = ((HashMap)data).keySet().iterator();
      String key = (String)(iter.next()); //키 가져오기
      System.out.println(key);
      return stringify((Object)key) + ":" + stringify((Object)(((HashMap)data).get(key))); //키 : 값
    }

    //2개 이상일 때 1(map) + n(data)개로 나눕니다.
    HashMap<Object,Object> head = new HashMap<>(); //새로운 해시맵 head
    Iterator<Object> iter = ((HashMap)data).keySet().iterator();
    String key = (String)(iter.next()); //키 가져오기
    head.put((Object)key,((HashMap)data).get(key)); //head에 1개 추가
    ((HashMap)data).remove(key);

    return mapRecursive(head) + "," + mapRecursive(data);
  }

배열과 마찬깆로 재귀적인 피보나치를 응용하였습니다. 맵의 1개 (키,값)쌍을 분리시켜 2개의 맵으로 나누어 감소식을 구현하였고 맵이 비어있을땐 단순히 빈 문자열을 반환, 1개 있을땐 키:값 문자열로 만들어 반환하여 종료조건을 구현하였습니다.




후기

반복문을 이용하면 쉽게 구현할 수 있지만, 어제 배웠던 재귀문을 더욱 견고히 익히기 위해 반복문을 사용하지 않고 재귀만을 이용하여 구현하였습니다. 감소식, 종료조건이 재귀함수의 핵심입니다.




GitHub

없음!

profile
오늘도 내일도 화이팅!

0개의 댓글