JSON 라이브러리를 추가하려고 프로젝트 우클릭 Configure - Convert To Maven Project 해서 pom.xml파일 생성
역시 한 번에 되면 재미없지 오류 발생
<build> 안에 넣어주란다. -> 넣어져있음
<plugin>으로 안 감싸져있어서 감싸줬더니 오류 또 발생
그래도 안 됐는데 <dependencies>안에 넣어주면 된다 !
코드는 여기서 가져왔다
https://mvnrepository.com/artifact/org.json/json/20230618
으잉.. 아니네 위에 오류가 있어서 안 떴나봐.. 안 된다
아니 <build> 안에 넣어주는게 아닌데 ???
pom.xml 파일 구조 참조한 블로그
https://velog.io/@coreminw/spring-Maven%EA%B3%BC-pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Mission01-web</groupId>
<artifactId>Mission01-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</build>
</project>
됐다.
잘 생겼다. 생각해보니 SQLite도 dependency 추가해줘야겠다.
<dependencies>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.36.0.3</version>
</dependency>
</dependencies>
JSONParser 쓰려고 라이브러리 또 추가
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<Open API에서 데이터 가져오기>
https://fbtmdwhd33.tistory.com/264
여기 참고했다.
<JSON 파싱>
일단 API에서 받아온 결과코드를 보면
{"TbPublicWifiInfo":{"list_total_count":23343,"RESULT":{"CODE":"INFO-000","MESSAGE":"정상 처리되었습니다"},"row":[{"X_SWIFI_MGR_NO":"---EP000001","X_SWIFI_WRDOFC":"은평구","X_SWIFI_MAIN_NM":"갈현1동주민센터","X_SWIFI_ADRES1":"갈현동 갈현로 301","X_SWIFI_ADRES2":"갈현1동 1층","X_SWIFI_INSTL_FLOOR":"","X_SWIFI_INSTL_TY":"7-1. 공공 - 행정","X_SWIFI_INSTL_MBY":"의견(자치)","X_SWIFI_SVC_SE":"공공WiFi","X_SWIFI_CMCWR":"자가망_U무선망","X_SWIFI_CNSTC_YEAR":"2011","X_SWIFI_INOUT_DOOR":"실내","X_SWIFI_REMARS3":"","LAT":"126.9167","LNT":"37.62364","WORK_DTTM":"2023-09-02 10:58:34.0"},
{ ....}, {....} 이런식으로 코드의 연속이고 ]}}
내가 필요한 정보들은 "row" : [ ... , ...] 이렇게 row 키 값에 value가 배열형태로 존재.
그러면 나는 제일 큰 중괄호를 object 파싱을 해야하고 그 안에 중괄호 안에 list_total_cout, Result, row 객체들이 있으니까 object 파싱을 한 번 더 해야한다.
json 파싱한 데이터를 WifiList DTO 객체에 저장할 필요성을 느꼈다.
<WifiList.java>
테이블의 객체 다 만들어주고 getter/setter 추가
이때 작업일시 type Date로 해주고 import java.util.Date;
이제 1. DB드라이버로드 2. connection 객체 생성 3. prepared 객체 생성 4. 쿼리 실행 5. 객체 닫기
과정을 통해서 openAPI로 불러온 정보들을 DB에 저장한다.
다 작성은 했는데 이런 오류 발생
pom.xml에 dependency추가해줬고 여기에 sqlite 라이브러리 있고 음.. url이 맞는진 모르겠지만
이렇게 연결도 해줬음.
위 코드로 db파일 생성까지 해줘서 빈 .db 파일이 (처음이자 마지막으로) 생성.
음 그러면 이게 내가 datagrip에서 미리 쿼리문으로 만들어놓은 테이블이 있는 db가 아닌가보다 ?
그럼 DataGrip에서 만든 db파일은 어디있을까나
찾았다
나같은 경우는 sqlite 설치파일 zip 을 dev_web폴더에 저장해놓았고
그 안에 있음.
이파일위치를 이클립스에서 연결해줘야 할 것 같다.
url을 이렇게 수정해줬더니 오류문구가 바뀌었다 !
manageno를 pk로 not null 옵션을 줬는데 없다는 오류
근데 manageno는 없을 수가 없는데 뭘까 파싱이 잘못 되었나 ?
이렇게 파싱해서 화면에 뽑아봤을 땐 잘 나왔음.. 음..
음... 근데 wifiList.getManageNo()를 출력했을 때는 null이 나온다 .값이 member객체에 세팅이 안 된다는 건데
알고보니 저기에 키 값하고 공백이 있어서 발생하는 거였음 !
공백 없애주고 실행시키니까
데이터 저장 ~~ 근데 왜 하나 밖에 안 됐지 ? 맨 마지막 데이터만 들어갔음 지금.
아 하나 wifiList에 세팅 되면 곧바로 db에 저장저장저장 계속 해줘야함 반복문 안에서
그러면 코드를 좀 정리를 해서 반복되는 드라이버 연결 같은 부분은 밖으로 빼주고 sql쿼리 실행하는 부분만 메소드로 만들어서 계속 호출할 수 있게 해줘야겠다.
해줬고
이제 해야할 일
: 모든 와이파이 데이터 저장먼저
총 데이터를 했더니만 이렇게 오류가 난다. API는 한 번에 최대 1000건만 가능하대
근데 이거를 야매로 그냥 숫자 바꿔서 해줘도 되겠지만
openAPI 와이파이 정보 가져오기 버튼을 눌렀을 때마다 ? API데이터가 싸악 저장이 되어야하는 거 같으니까
코드로 만들어보자. 근데 총 데이터 갯수를 어떻게 알지 ? 아 json 파싱한 거에 나와있따.
실시간 저장이 아니라고 한다. 그럼 누를 때마다 API데이터를 db에 저장하는 것이 아닌 이미 저장해 놓고 불러오는 방식을 의미하는 것 같다 !
아무튼 그래서 1000건씩 계속 데이터 시작행, 마지막 행 숫자 바꿔가면서 하고 있는데 저장은 재빨리 되는데 이클립스에서 렉이 너무 많이 걸린다. 1000번을 계속 드라이버 연결하고 해제해주고 하는 작업 때문인 듯.. . 코드 수정을 좀 다시 해야겠다.
날아가서 다시 ..
1. jdbc 드라이버 연결 & API 정보 가져오는 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class APITest {
static {
// 1. 드라이버 연결
//2. connection 객체 생성
//3. statement 객체 생성
//4. 쿼리 실행
//5. 결과 수행(insert경우)
//6. 객체 연결 해제
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection connection = null;
PreparedStatement preparedStatement = null;
String url_value = "jdbc:sqlite:C:\\dev_web\\sqlite-tools-win32-x86-3430000wifi.db";
try {
connection = DriverManager.getConnection(url_value);
} catch (SQLException e){
e.printStackTrace();
}
}
public static void main(String args[]) throws IOException {
//1. url 만들기 위한 StringBuilder
StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088");
//2. 오픈 API의 요청 규격에 맞는 파라미터 생성, 발급받은 인증키
urlBuilder.append("/" + URLEncoder.encode("4b78435972736f6534356e73497157","UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("json","UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("TbPublicWifiInfo", "UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("1","UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("3","UTF-8"));
//3. URL 객체 생성
URL url = new URL(urlBuilder.toString());
//4. 요청하고자 하는 url과 통신하기 위한 Connection 객체 생성
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//5. 통신을 위한 메소드 set
conn.setRequestMethod("GET");
//6. 통신을 위한 content-type set
conn.setRequestProperty("Content-type", "application/json");
//7. 통신 응답코드 확인
System.out.println("Response Code : " + conn.getResponseCode());
//8. 전달받은 데이터를 BufferedReader 객체로 저장.
BufferedReader rd;
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
//9. 저장된 데이터 라인별로 읽어 StringBuilder 객체로 저장
StringBuilder sb = new StringBuilder();
String line;
while((line = rd.readLine()) != null) {
sb.append(line);
}
//10. 객체 해제
rd.close();
conn.disconnect();
//11. 전달받은 데이터 확인
System.out.println(sb.toString());
}
}
1. 문자열 형태로 날아오는 결과 json을 파싱하기 위한 JSONParser 객체 생성
import org.json.simple.parser.JSONParser;
//json-simple 라이브러리 pom.xml에 dependency 해줘야 함.
JSONParser parser = new JSONParser();
2. 문자열을 JSON 형태로 JSONObject 객체에 저장.
import org.json.JSONObject;
import org.json.simple.parser.ParseException;
//2. 문자열을 JSON 형태로 JSONObject 객체에 저장.
JSONObject obj = null;
try {
obj = (JSONObject)parser.parse(sb.toString());
} catch (ParseException e) {
e.printStackTrace();
}
이렇게 하면 key : value 형태가 obj에 저장.
내가 필요한 정보는
{"TbPublicWifiInfo":{"list_total_count":23343,"RESULT":{"CODE":"INFO-000","MESSAGE":"정상 처리되었습니다"},"row":[{"X_SWIFI_MGR_NO":"---EP000001","X_SWIFI_WRDOFC":"은평구","X_SWIFI_MAIN_NM":"갈현1동주민센터","X_SWIFI_ADRES1":"갈현동 갈현로 301","X_SWIFI_ADRES2":"갈현1동 1층","X_SWIFI_INSTL_FLOOR":"","X_SWIFI_INSTL_TY":"7-1. 공공 - 행정","X_SWIFI_INSTL_MBY":"의견(자치)","X_SWIFI_SVC_SE":"공공WiFi","X_SWIFI_CMCWR":"자가망_U무선망","X_SWIFI_CNSTC_YEAR":"2011","X_SWIFI_INOUT_DOOR":"실내","X_SWIFI_REMARS3":"","LAT":"126.9167","LNT":"37.62364","WORK_DTTM":"2023-09-02 10:58:34.0"} ] } }
이렇게 하나의 obj 안에 key가 TbPublicWifiInfo이고 그 안에 value 중에서도 또 키와 값으로 이루어진 row 값이 필요함.
row는 jsonArray 형태로 구성돼있음.
결론은 나는 object 파싱을 2번 해준다음 row키 값으로 jsonArray파싱을 해줘야 원하는 값들을 얻을 수 있다.
- jsonArray 사용 참고
https://codechacha.com/ko/java-parse-json/#object
https://studyingazae.tistory.com/196
APITest 풀코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class APITest {
public static void main(String args[]) throws IOException {
// 1. 드라이버 연결
// 2. connection 객체 생성
// 3. statement 객체 생성
// 4. 쿼리 실행
// 5. 결과 수행(insert경우)
// 6. 객체 연결 해제
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection connection = null;
PreparedStatement preparedStatement = null;
String url_value = "jdbc:sqlite:C:\\dev_web\\sqlite-tools-win32-x86-3430000\\wifi.db";
try {
connection = DriverManager.getConnection(url_value);
} catch (SQLException e) {
e.printStackTrace();
}
// 1. url 만들기 위한 StringBuilder
StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088");
// 2. 오픈 API의 요청 규격에 맞는 파라미터 생성, 발급받은 인증키
urlBuilder.append("/" + URLEncoder.encode("4b78435972736f6534356e73497157", "UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("json", "UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("TbPublicWifiInfo", "UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("1", "UTF-8"));
urlBuilder.append("/" + URLEncoder.encode("3", "UTF-8"));
// 3. URL 객체 생성
URL url = new URL(urlBuilder.toString());
// 4. 요청하고자 하는 url과 통신하기 위한 Connection 객체 생성
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 5. 통신을 위한 메소드 set
conn.setRequestMethod("GET");
// 6. 통신을 위한 content-type set
conn.setRequestProperty("Content-type", "application/json");
// 7. 통신 응답코드 확인
System.out.println("Response Code : " + conn.getResponseCode());
// 8. 전달받은 데이터를 BufferedReader 객체로 저장.
BufferedReader rd;
if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
// 9. 저장된 데이터 라인별로 읽어 StringBuilder 객체로 저장
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
// 10. 객체 해제
rd.close();
conn.disconnect();
// 11. 전달받은 데이터 확인
System.out.println(sb.toString());
// JSON 파싱
// 1. 문자열 형태의 JSOn 파싱하기 위한 JSONParser 객체 생성.
JSONParser parser = new JSONParser();
// 2. 문자열을 JSON 형태로 JSONObject 객체에 저장.
JSONObject obj = null;
try {
obj = (JSONObject) parser.parse(sb.toString());
} catch (ParseException e) {
e.printStackTrace();
}
// 3. 한 번 더 Parsing
JSONObject second = (JSONObject) obj.get("TbPublicWifiInfo");
// 4. row 키 값으로 배열을 JSONArray에 가져옴
JSONArray jArray = (JSONArray)second.get("row");
int affected = 0;
for (int i = 0; i < jArray.size(); i++) {
WifiList wifiList = new WifiList();
JSONObject o = (JSONObject)jArray.get(i);
wifiList.setManageNo((String) o.get("X_SWIFI_MGR_NO"));
// wifiList.setDist((String)o.get(거리));
wifiList.setGugun((String) o.get("X_SWIFI_WRDOFC"));
wifiList.setWifiName((String) o.get("X_SWIFI_MAIN_NM"));
wifiList.setAddress((String) o.get("X_SWIFI_ADRES1"));
wifiList.setDetailAddress((String) o.get("X_SWIFI_ADRES2"));
wifiList.setSetFloor((String) o.get("X_SWIFI_INSTL_FLOOR"));
wifiList.setSetType((String) o.get("X_SWIFI_INSTL_TY"));
wifiList.setSetOrgan((String) o.get("X_SWIFI_INSTL_MBY"));
wifiList.setServiceDivision((String) o.get("X_SWIFI_SVC_SE"));
wifiList.setNetworkKind((String) o.get("X_SWIFI_CMCWR"));
wifiList.setSetYear(Integer.parseInt((String)o.get("X_SWIFI_CNSTC_YEAR")));
wifiList.setInOutdoor((String) o.get("X_SWIFI_INOUT_DOOR"));
wifiList.setWificonnectEnvirionment((String) o.get("X_SWIFI_REMARS3"));
wifiList.setX(Double.parseDouble((String)o.get("LAT")));
wifiList.setY(Double.parseDouble((String)o.get("LNT")));
// wifiList.setWorkDate((java.sql.Date)o.getDate("WORK_DTTM"));
String sql = "insert into wifi_list (manage_no, dist, gugun, wifi_name, address, detail_address, set_floor, set_type, set_organ, service_division, network_kind, "
+ "set_year, in_outdoor, wificonnect_environment, x, y, work_date)"
+ " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try {
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, wifiList.getManageNo());
preparedStatement.setDouble(2, wifiList.getDist());
preparedStatement.setString(3, wifiList.getGugun());
preparedStatement.setString(4, wifiList.getWifiName());
preparedStatement.setString(5, wifiList.getAddress());
preparedStatement.setString(6, wifiList.getDetailAddress());
preparedStatement.setString(7, wifiList.getSetFloor());
preparedStatement.setString(8, wifiList.getSetType());
preparedStatement.setString(9, wifiList.getSetOrgan());
preparedStatement.setString(10, wifiList.getServiceDivision());
preparedStatement.setString(11, wifiList.getNetworkKind());
preparedStatement.setInt(12, wifiList.getSetYear());
preparedStatement.setString(13, wifiList.getInOutdoor());
preparedStatement.setString(14, wifiList.getWificonnectEnvirionment());
preparedStatement.setDouble(15, wifiList.getX());
preparedStatement.setDouble(16, wifiList.getY());
preparedStatement.setDate(17, (Date) wifiList.getWorkDate());
affected += preparedStatement.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(affected+"개 저장 완료");
try {
if(preparedStatement != null && !preparedStatement.isClosed()) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
여기서 Date 저장을 아직 못 하고 있다.
그냥 String으로 받음 !
한 번에 API 요청 1000건 밖에 안 돼서 나눠서 저장을 했다.
여기서 중요한 건 manageNo를 PK처리 해줘야 데이터 중복 저장이 안 됨 !
혹시나 나중에 json 다른 형태로 받고 싶을 때 참조
https://jhyonhyon.tistory.com/11
'공부 > Trouble Shooting' 카테고리의 다른 글
자바스크립트에서 자바 함수 호출 (0) | 2023.09.06 |
---|---|
이클립스 깃허브 연결 (0) | 2023.09.04 |
ExERD 이클립스 플러그인으로 설치 (0) | 2023.08.31 |
인텔리제이에 mariadb 연결과정 (SELECT) (0) | 2023.08.30 |
윈도우 파일 우분투로 전송 (0) | 2023.08.26 |