JSON이란? 속성-값 쌍 또는 키-값 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다. 비동기 브라우저/서버 통신 을 위해, 넓게는 XML을 대체하는 주요 데이터 포맷이다.
XML이란? W3C에서 개발된, 다른 특수한 목적을 갖는 마크업 언어를 만드는데 사용하도록 권장하는 다목적 마크업 언어이다.
1) JSON 파싱
mvnrepository.com/artifact/org.json/json
위 MavenRepository에 들어가서 JSON을 파싱하여 사용하기 위한 라이브러리를 다운받아서 프로젝트에 등록한다.
//StringBuffer를 쓴 이유는? String은 불변의 특징이 있으므로, 너무 많은 문자열 상수를 만들어내지 않기 위해
StringBuffer sb = new StringBuffer();
sb.append("{");
sb.append("\"name\":\"hyuk\"");
sb.append("}");
//sb에 담겨진 표기는, 실제 JSON 객체는 아니므로, 파싱단계를 거쳐 JSON 객체로 전환해야 한다!!
//JSON파서는 자바 자체적으로 지원하지 않으므로 외부 라이브러리를 이용하여 파싱업무를 시도하자!!
//주로 무료 기반(오픈소스)의 외부 라이브러는 아파치 재단에서 운영되는 maven 사이트 이용하자!
JSONParser jsonParser = new JSONParser();//구문을 분석하는 파서객체 생성
try {
JSONObject obj = (JSONObject)jsonParser.parse(sb.toString());//파싱시작!!
//파싱이 완료된 이후부터는 더이상 문자열이 아닌, json 객체로 사용하면 된다!!
//JSON은 키와 밸류의 형태!!!
System.out.println(obj.get("name"));//get(키값)
} catch (ParseException e) {
e.printStackTrace();
}
}
JSONParser를 이용하여 파싱을 하여 JSONObject 객체로 반환받아서 JSON데이터의 키값을 이용하여 값을 얻어올 수 있다!!
2) XML 파싱
XML 파싱은 JSON과 다르게 좀 더 복잡하다..
- jAVA에서 제공하는 SAXParser라는 추상 클래스를 제공한다.
- SAXParser는 SAXParserFactory의 newSAXParser()메서드를 이용하여 인스턴스를 얻을 수 있다.
- SAXParserFactory는 추상클래스로 SAXParserFactory의 static메서드인 newInstance()를 이용하여 인스턴스를 얻을 수 있다.
- SAXParser는 DefaultHandler를 상속받는 핸들러클래스를 재정의하여 파싱할 수 있다...
- 말만 들어도 복잡하다..
<?xml version="1.0" encoding="UTF-8"?>
<pets>
<pet>
<type>dog</type>
<name>뽀미</name>
<age>9</age>
<gender>여</gender>
</pet>
<pet>
<type>cat</type>
<name>나비</name>
<age>3</age>
<gender>여</gender>
</pet>
</pets>
이러한 XML파일이 있다. 파싱을 하기 위해
/*
XML의 모든 노드에서 이벤트가 발생할때마다 아래의 핸들러 객체의 메서드를
알맞게 오버라이드하면 됨.
*/
package day1113.xml;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyHandler extends DefaultHandler {
ArrayList<Pet> petList;
Pet pet;
boolean isType;
boolean isName;
boolean isAge;
boolean isGender;
// 문서가 시작되면 호출됨
@Override
public void startDocument() throws SAXException {
System.out.println("문서를 시작합니다");
}
// 여는 태그 만났을때 호출됨 <태그> (/가 없는 태그)
@Override
public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
System.out.print("<" + tag + ">");
// 여러 태그 중 pets를 만나면 ArrayList를 생성하자!!
if (tag.equals("pets")) {
petList = new ArrayList<Pet>();
} else if (tag.equals("pet")) { // 하나의 pet 인스턴스 생성할 타임이다!!
pet = new Pet();
} else if (tag.equals("type")) { // ???
// 시작 태그를 지금 지나가고 있음을 알려주자!!!
isType = true;
} else if (tag.equals("name")) { // ???
isName = true;
} else if (tag.equals("age")) { // ???
isAge = true;
} else if (tag.equals("gender")) { // ???
isGender = true;
}
}
// 태그와 태그사이의 데이터를 만났을 때 호출
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String data = new String(ch, start, length);
System.out.print(data);
if(isType) {
pet.setType(data);
}else if(isName) {
pet.setName(data);
}else if(isAge) {
pet.setAge(Integer.parseInt(data));
}else if(isGender) {
pet.setGender(data);
}
}
// 닫는 태그를 만났을 때
@Override
public void endElement(String uri, String localName, String tag) throws SAXException {
System.out.print("</" + tag + ">");
if (tag.equals("pet")) { // 이 시점에 하나의 Pet이 완성된 시점이므로, 리스트에 담아두자!!
petList.add(pet);
} else if (tag.equals("type")) { // ???
// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화!!
isType = false;
} else if (tag.equals("name")) { // ???
// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
isName = false;
} else if (tag.equals("age")) { // ???
// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
isAge = false;
} else if (tag.equals("gender")) { // ???
// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
isGender = false;
}
}
// 문서가 끝날 때
@Override
public void endDocument() throws SAXException {
System.out.println("문서를 종료합니다");
System.out.println("결과 보고서 : 총 " + petList.size() + "가 존재합니다.");
for(Pet pet : petList) {
System.out.println("type : " + pet.getType());
System.out.println("name : " + pet.getName());
System.out.println("age : " + pet.getAge());
System.out.println("gender : " + pet.getGender());
System.out.println("-------------------------------------------");
}
}
}
startDocument 메서드는 문서시작 시 호출되는 메서드
startElement 메서드는 열린태그를 만났을 시 호출되는 메서드
characters 메서드는 태그안의 데이터를 만났을 시 호출되는 메서드
endElement 메서드는 닫는태그를 만났을 시 호출되는 메서드
endDocument 메서드는 문서 종료 시 호출되는 메서드
위 코드를 보면 어떤 형식으로 진행되는지 이해할 수 있을 것이다..
아래는 재정의한 핸들러를 사용하여 xml을 파싱하는 코드)
/*
* java로 xml를 파싱하는 방법은 크게 2가지 있다.
* 1)DOM 방식 - html과 같은 원리...
* 즉, 모든 태그마다 1:1대응하는 DOM객체를 메모리에 생성해놓고 프로그래밍언어에서 필요한 객체를 접근하는 방식
* 예) javascript - DOM
* 무거운 DOM객체가 메모리에 부하를 일으킬 수 있다.. 특히 메모리크기가 pc에 비해 상대적으로 작은 디바이스의 경우 DOM방식은 적절치못하다!!
* 2)SAX 방식 - xml문서를 이루는 엘리먼트, 텍스트 등의 모든 노드에 대한 이벤트를 발생시켜주는 방식
* 따라서 개발자는 적절한 자바의 객체를 메모리에 올려, xml을 대신하여 데이터를 사용하면 된다!!
*
*/
package day1113.xml;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class XMLParseApp {
// 실행중인 자바프로세스가 파일에 접근하기 위해서는 파일입력스트림 계열이 필요하다!
FileInputStream fis;
InputStreamReader reader;
BufferedReader buffr;
File file;
URL url;
URI uri;
public XMLParseApp() {
url = this.getClass().getClassLoader().getResource("res/pets.xml");
try {
uri = url.toURI(); // File 클래스의 생성자에서는 URL이 아닌 URI를 원하므로, 변환하자!
fis = new FileInputStream(file = new File(uri)); //스트림얻기!! 현재 1byte씩얻는상태
parseData(); //파싱시작!!
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//xml파싱해보자!!
public void parseData() {
//SAX방식의 파서는 SAXParserFactory 객체로부터 얻는다.
SAXParserFactory factory;
factory = SAXParserFactory.newInstance(); //static메서드를 이용하여 인스턴스얻음
try {
SAXParser saxParser=factory.newSAXParser();//Factory로부터 파서의 인스턴스를 얻을 수 있다..
saxParser.parse(fis, new MyHandler());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readTest() {
try {
//육안으로 확인할 때 한글이 깨질 수 있으므로, Reader로 업그레이드하자
reader = new InputStreamReader(fis); //문자로 얻는 걸로 업그레이드
buffr = new BufferedReader(reader);// 한 줄씩 얻는 걸로 업그레이드
//한문자씩 읽어들이면 너무 시간이 오래걸리므로, 한줄씩 읽어 들이기
//파싱은 나중에하고, 먼저 xml을 제대로 스트림으로 읽어들일 수 있는 지 체크
String data = null;
while(true) {
data = buffr.readLine();
if(data==null) break;
System.out.println(data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new XMLParseApp();
}
}
Pet클래스(VO)
/*
한마리의 반려동물을 담게 될 VO 클래스
VO란? Value Object의 약자로서, [로직 작성이 목적이 아닌 단지 데이터만을 보관할 용도로 사용되는 객체]를 가리키는 애플리케이션 설계 용어 중 하나!
*/
package day1113.xml;
public class Pet {
private String type;
private String name;
private int age;
private String gender;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
지금봐도 너무 어렵다... 여러번 봐야할 것 같다.. ㅠ
'프로그래밍 > Java' 카테고리의 다른 글
java - mail 보내기 (0) | 2021.01.06 |
---|---|
싱글톤 패턴 알아보기 (0) | 2020.12.14 |
JavaFX - 개발환경 구축 및 생명주기 (0) | 2020.11.23 |
Java - 소켓프로그래밍 기초 Echo System (0) | 2020.11.09 |
Java - JDBC(Java DataBase Connectiviy) 사용법 (0) | 2020.11.05 |