먼저 이 글을 보기 전에 알고 있으면 더 좋은 글입니다.


1번. MySQL JSON DATA TYPE

2018/11/30 - [Develop/MySQL] - [MySQL] MySQL JSON - MySQL 5.7 JSON Functions



2번. MySQL에서의 '일반' 값을 JSON형식으로 가져오기

2018/10/28 - [Develop/Spring Boot] - Spring boot JPA EntityManager를 이용한 Map형식으로 mapping하기

2018/10/24 - [Develop/Spring Boot] - Spring boot jpa map, hashmap, JSON형식


3번. JSON PARSING

2018/11/13 - [Develop/Spring Boot] - Spring Boot Json, hashmap to json , JsonObject 만들기- JSON 마지막

2018/11/12 - [Develop/Spring Boot] - Spring Boot Deserialization Json, Deserialization JsonString to JsonObject - Json 4편

2018/11/09 - [Develop/Spring Boot] - Spring Boot Json, Jackson을 이용한 JsonParsing - Json 3편

2018/11/07 - [Develop/Spring Boot] - Spring Boot Json, Gson을 이용한 JsonObject to String, String to JsonObject- JSON 2편

2018/11/06 - [Develop/Spring Boot] - Spring Boot Json, JsonObject로 만들기 - JSON 1편



나도 SPRING BOOT 에서 어떻게 가져오는지 많이 검색해봤으나. 자료가 거의 없어서 열심히 삽질했던 것 같다.

수 많은 삽질 끝에 알아내서 필요한 곳에 사용중이다.


이번 글은 MySQL에서 SELECT시 일반 DATA 형식이 아닌 JSON DATA TYPE을 SPRING BOOT 에 SELECT하는 내용이다.

우선 일반 DATA형식은 그냥 말그대로 SELECT id, name FROM test 해서 가져오는 내용들이고

JSON DATA TYPE 형식은 위의 1번 링크에서 확인할 수 있다.



1. 우선 이번에 사용할 예제 테이블 및 데이터이다. 1번링크에서 확인 가능하다.



2. 먼저 JSON DATA TYPE을 불러올 코드를 작성한다.


아래의 코드를 보면 CONCAT_WS('\\\\',  부분이 있다.


사실 JSON DATA TYPE을 가져올 때 JSON_OBJECT를 사용하면 가져올 수 있으나. 사용하는 이유는


SPRING BOOT에서 CONCAT_WS('\\\\',  를 사용하지 않으면 MySQL에서 값을 불러올때 쌍따옴표를 지워버린다. 


그래서 만약 CONCAT_WS를 사용하지않고 JSON_OBJECT만을 이용하여 SELECT하면


ex) {"ID": 1, "NAME": "TEST", "PASSWORD": "1234", "PHONE_NUM": "010-1111-1111"} 이렇게 불러와야할 값이

     {"    이렇게 나오고 뒤의 내용은 다 짤려버린다.


그래서 CONCAT_WS 함수를 이용하여 쌍따옴표가 안짤리고 SELECT하기 위해 앞에 역슬래쉬를 붙인다. 


4개 붙이는 이유는 두개 붙이니까 SPRING BOOT단에서 짤려버리더라...... 그래서 4개 붙인다.


그리고 CONCAT_WS를 사용하면 값을 Byte로 불러온다.  그래서 String 형식이나 기타 외의 데이터로는 불러오지 못하므로


항상 Object 데이터 형식을 사용해서 불러와야 한다. 그 후 Object를 Byte로 변환 그리고 Byte를  String으로 변환하는 방법 등을 사용 해야 한다.


아래의 코드에서도 우선 List로 결과를 불러오고 Object를 통해 Byte로 변환 그리고 Byte를 다시 String으로 변환한다.


@GetMapping("/test")
	public void test() {
		Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
				+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
				+ "as TEST " + "FROM " + "test t");

		List r = query.getResultList();
		for (Object obj : r) {
			byte[] b = (byte[]) obj;
			String value = new String(b, StandardCharsets.UTF_8);
			System.out.println(value);
		}
}


위 코드를 실행하면 아래와 같은 JSON 타입의 내용을 Spring Boot에서 불러올 수 있다.




3.  이 Json String을 JsonObject로 만들어보자 


3번 링크의 Gson이나 Jackson, JsonObject 등등 을 이용하여 만들 수 있다.


Jackson을 이용하여 한번 만들어 보겠다.


먼저 TestDTO 클래스를 하나 만든다 

3번링크의 Json 1편의 DTO에서 password와 phone_num 변수를 추가한다.


만든 후 현재 데이터를 2개가 불러오기 때문에 객체 배열로 생성하였다.

그 후 각 클래스 배열마다 Jackson의 objectmapper를 사용하여 Json String을 Json Object로 변환시켜주었다.


Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
				+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
				+ "as TEST " + "FROM " + "test t");


		List r = query.getResultList();
		
		ObjectMapper objectMapper = new ObjectMapper();
		TestDTO t[] = new TestDTO[r.size()];
		int i=0;
		
		for (Object obj : r) {
			byte[] b = (byte[]) obj;
			String value = new String(b, StandardCharsets.UTF_8);
			try {
				
				t[i]= objectMapper.readValue(value, TestDTO.class);
				i++;
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		for(TestDTO test : t) {
			System.out.println(test.getId());
			System.out.println(test.getPassword());
			System.out.println(test.getName());
			System.out.println(test.getPhone_num());
			System.out.println();
		}

아래와 같이 결과가 나온다


이것을 많은 형식을 이용하여 불러 올 수있다 2번링크를 사용하여 애초에  Map으로 불러와서 mapping시키거나 할 수 있다.


Map으로 불러와서 mapping할 경우 문제점은 정규식을 통해 파싱해줘야 하는 단점이있다.


왜냐하면 Json값이 { "id" : 1 } 이렇다면 Map으로 불러올경우 "{ "id" : 1 }" 이렇게 중괄호에 쌍따옴표가 붙어버린다.


그래서 정규식을 통해 중괄호의 쌍따옴표만 지워야 하는 단점이 있다. 하지만 나는 이러한 단점에도 불구하고도 


JSON_TYPE과 함께 일반 데이터까지 가지의 값을 가져 와야하기 때문에 자주 사용한다.

어찌보면 가장 중요한 Deserialization한 JsonString 형태를 파싱하는 방법이다.

Spring Boot에서 Deserialization 파싱을 위해 Jackson과 gson을 사용하면서 동시에 클래스를 생성하여 사용해야한다.



Spring boot Json 1편, 2편, 3편, 마지막

1. 2018/11/06 - [Spring Boot] - Spring Boot Json, JsonObject로 만들기 - JSON 1편

2. 2018/11/07 - [Develop/Spring Boot] - Spring Boot Json, Gson을 이용한 JsonObject to String, String to JsonObject- JSON 2편

3. 2018/11/09 - [Develop/Spring Boot] - Spring Boot Json, Jackson을 이용한 JsonParsing - Json 3편

4. 2018/11/13 - [Develop/Spring Boot] - Spring Boot Json, hashmap to json , JsonObject 만들기- JSON 마지막



번외 Database의 값을 Json으로 select하는 방법.

1. 2018/10/24 - [Spring Boot] - Spring boot jpa map, hashmap, JSON형식

2. 2018/10/28 - [Spring Boot] - Spring boot JPA EntityManager를 이용한 Map형식으로 mapping하기


Spring boot에서 MySQL JSON 타입 SELECT하는 방법

1. 2018/11/30 - [Develop/Spring Boot] - Spring boot MySQL JSON - MySQL JSON DATA TYPE 값 가져오기



1. Class를 생성하여 Gson을 이용한 Deserializaion한 JsonString to Object(JsonObject)


앞의 1편, 2편, 3편에 사용했던 TestDTO를 수정하자.


수정하기 전 먼저 Test_2DTO를 새로 생성한다


public class Test_2DTO {
	private String name;
	private int age;
	
	public Test_2DTO() {
		super();
	}

	public Test_2DTO(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}
public class TestDTO {

	private Integer id;
	private String password;
	private List details;
	
	
	public TestDTO() {
		super();
	}


	public TestDTO(Integer id, String password, List details) {
		super();
		this.id = id;
		this.password = password;
		this.details = details;
	}


	public Integer getId() {
		return id;
	}


	public void setId(Integer id) {
		this.id = id;
	}


	public String getPassword() {
		return password;
	}


	public void setPassword(String password) {
		this.password = password;
	}


	public List getDetails() {
		return details;
	}


	public void setDetails(List details) {
		this.details = details;
	}


	@Override
	public String toString() {
		return new Gson().toJson(this);
	}
}


생성했다면, 


public void test() {
		
		String jsonString = "{\r\n" + 
				"    \"id\": 1,\r\n" + 
				"    \"password\": \"1234\",\r\n" + 
				"    \"details\": [\r\n" + 
				"        {\r\n" + 
				"            \"name\": \"test\",\r\n" + 
				"            \"age\": 20\r\n" + 
				"        },{\r\n" + 
				"            \"name\": \"test2\",\r\n" + 
				"            \"age\": 21\r\n" + 
				"        }\r\n" + 
				"    ] \r\n" + 
				"}";
		Gson gson = new Gson();
		TestDTO t = gson.fromJson(jsonString, TestDTO.class);
		System.out.println("id : " +t.getId());
		System.out.println("password : "+t.getPassword());
		System.out.println("name1 : "+t.getDetails().get(0).getName());
		System.out.println("age1: "+t.getDetails().get(0).getAge());
		System.out.println("name2 : "+t.getDetails().get(1).getName());
		System.out.println("age2: "+t.getDetails().get(1).getAge());
		
	}

위에 사용한 Json내용이다., 


{
    "id": 1,
    "password": "1234",
    "details": [
        {
            "name": "test",
            "age": 20
        },{
            "name": "test2",
            "age": 21
        }
    ] 
}


위 test() 메소드를 실행하면 아래와 같이 Deserializaion한 JsonString이 파싱되어 JsonObject에 알맞게 들어간다.



2. Jackson의 ObjectMapper를 이용한 Json String to JsonObject 이다.


Json내용은 위와 동일한 상태에서 진행하였다.


public void test() {
		ObjectMapper objectMapper = new ObjectMapper();
		 
		String jsonString = "{\r\n" + 
				"    \"id\": 1,\r\n" + 
				"    \"password\": \"1234\",\r\n" + 
				"    \"details\": [\r\n" + 
				"        {\r\n" + 
				"            \"name\": \"test\",\r\n" + 
				"            \"age\": 20\r\n" + 
				"        },{\r\n" + 
				"            \"name\": \"test2\",\r\n" + 
				"            \"age\": 21\r\n" + 
				"        }\r\n" + 
				"    ] \r\n" + 
				"}";
		  try {
	            TestDTO t = objectMapper.readValue(jsonString, TestDTO.class);    // String to Object로 변환
	            System.out.println("ObjectMapper테스트");
	    		System.out.println("id : " +t.getId());
	    		System.out.println("password : "+t.getPassword());
	    		System.out.println("name1 : "+t.getDetails().get(0).getName());
	    		System.out.println("age1: "+t.getDetails().get(0).getAge());
	    		System.out.println("name2 : "+t.getDetails().get(1).getName());
	    		System.out.println("age2: "+t.getDetails().get(1).getAge());	     
	
	        } catch (IOException e) {
	            e.printStackTrace();
	        }		
}

gson과 마찬가지로 잘 작동된다.


3. Jackson JsonNode 를 이용한 Deserializaion String to JsonObject


어떻게 보면 가장 핵심인 부분일 수도 있다. 클래스 생성없이 할 수 있다는 큰 장점이있다.


Deserializaion Json Data는 위와 동일한 데이터를 사용한다.



public void test() {
		ObjectMapper objectMapper = new ObjectMapper();

		String jsonString = "{\r\n" + "    \"id\": 1,\r\n" + "    \"password\": \"1234\",\r\n"
				+ "    \"details\": [\r\n" + "        {\r\n" + "            \"name\": \"test\",\r\n"
				+ "            \"age\": 20\r\n" + "        },{\r\n" + "            \"name\": \"test2\",\r\n"
				+ "            \"age\": 21\r\n" + "        }\r\n" + "    ] \r\n" + "}";
		try {
			System.out.println("Jackson JsonNode 테스트");
			JsonNode t = objectMapper.readValue(jsonString, JsonNode.class); // String to Object로 변환
			
			JsonNode id = t.get("id");
			System.out.println("id : " + id.asInt());
			
			JsonNode password = t.get("password");
			System.out.println("password : " + password.asText());
			
			JsonNode details = t.get("details");
			JsonNode details_1 = details.get(0);		
			System.out.println("name1 : " + details_1.get("name").asText());
			System.out.println("age1: " + details_1.get("age").asInt());
			
			JsonNode details_2 = details.get(1);	
			System.out.println("name2 : " + details_2.get("name").asText());
			System.out.println("age2: " + details_2.get("name").asText());

		} catch (IOException e) {
			e.printStackTrace();
		}
}

class 생성없이 파싱이 잘 되었다


이 처럼 웬만한 것들은 class를 생성하여 모든 Deserializaion을 파싱할 수 있으며,

Jackson JsonNode 를 이용하여 처리할 수 있다. 


Spring Boot에서 Json 파싱을 위해 Jackson을 기본적으로 제공해준다. Spring에서는 maven 또는 gradle을 xml에 추가해야한다.

사실 기본적인 기능은 앞선 gson과 다를게 없다.


Spring boot Json 1편, 2편, 4편, 마지막

1. 2018/11/06 - [Spring Boot] - Spring Boot Json, JsonObject로 만들기 - JSON 1편

2. 2018/11/07 - [Develop/Spring Boot] - Spring Boot Json, Gson을 이용한 JsonObject to String, String to JsonObject- JSON 2편

3. 2018/11/12 - [Develop/Spring Boot] - Spring Boot Deserialization Json, Deserialization JsonString to JsonObject - Json 4편

4. 2018/11/13 - [Develop/Spring Boot] - Spring Boot Json, hashmap to json , JsonObject 만들기- JSON 마지막




번외 Database의 값을 Json으로 select하는 방법.

1. 2018/10/24 - [Spring Boot] - Spring boot jpa map, hashmap, JSON형식

2. 2018/10/28 - [Spring Boot] - Spring boot JPA EntityManager를 이용한 Map형식으로 mapping하기


Spring boot에서 MySQL JSON 타입 SELECT하는 방법

1. 2018/11/30 - [Develop/Spring Boot] - Spring boot MySQL JSON - MySQL JSON DATA TYPE 값 가져오기



1. Jackson ObjectMapper (JsonString to Object)


public void test() {
		ObjectMapper objectMapper = new ObjectMapper();

		String Json =
		    "{ \"id\" : 1, \"password\" : \"1234\" }";

		try {
		    TestDTO t = objectMapper.readValue(Json, TestDTO.class);	// String to Object로 변환

		    System.out.println("id = " + t.getId());
		    System.out.println("password = " + t.getPassword());
		    
		    String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(t); //다시 jsonString으로 변환
		    System.out.println(jsonString);
		} catch (IOException e) {
		    e.printStackTrace();
		}
}


(위의 TestDTO은 1편에 나와있다.)


objectMapper를 통해 JsonString을 Object로 변환할 수 있었고 writeValueAsString을 통해 다시 JsonString으로도 변환이 가능하다


2. Object From JsonFile



ObjectMapper objectMapper = new ObjectMapper();

URL url = new URL("file:data/test.json");

TestDTO t = objectMapper.readValue(url, TestDTO.class);


test.json 파일엔

{

"id" : 1,

"password" : 1234

}

들어 가있다.



기본적인 사용방법은 여기까지이다 다음편에 Jackson JsonNodeClass를 설명한다.

Jackson 가이드 - https://www.baeldung.com/jackson

+ Recent posts