자바 JSON 예제 튜토리얼에 오신 것을 환영합니다. JSON (JavaScript Object Notation)은 인간이 읽을 수 있는 형식으로 구성된 가벼운 텍스트 기술입니다. JSON은 키-값 쌍 형태로 개체 데이터를 나타냅니다. 중첩된 JSON 개체도 사용할 수 있으며 배열을 나타내는 간단한 방법을 제공합니다.
Java JSON
JSON은 XML보다 가볍고 더 간결하기 때문에 웹 응용 프로그램이나 서버 응답에서 널리 사용됩니다. JSON 개체는 읽고 쓰기 쉽고 대부분의 기술에서 JSON 개체를 지원합니다. 그래서 자바 웹 서비스에서 JSON이 매우 인기가 있습니다. JSR353은 마침내 Java EE 7로 채택되었으며, 이것은 Java JSON 처리 API입니다. jsonp은 Java JSON 처리 API의 참조 구현체입니다. 이를 maven 프로젝트에 다음 종속성을 추가하여 사용할 수 있습니다.
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.2</version>
</dependency>
GlassFish 4.0을 사용하는 경우 범위를 제공된 것으로 유지할 수 있습니다. 왜냐하면 이미 서버에 포함되어 있기 때문입니다. JSON API는 JSON 처리를 위해 두 가지 방법을 제공합니다:
- 객체 모델 API – 이는 DOM 파서와 유사하며 작은 객체에 적합합니다.
- 스트리밍 API – 이는 StaX 파서와 비슷하며, 전체 객체를 메모리에 보관하지 않아도되는 큰 객체에 적합합니다.
Java JSON API의 일부 중요한 인터페이스는 다음과 같습니다:
- javax.json.JsonReader: 이를 사용하여 JSON 개체 또는 배열을 JsonObject로 읽을 수 있습니다. JsonReader를 Json 클래스 또는 JsonReaderFactory에서 가져올 수 있습니다.
- javax.json.JsonWriter: 이를 사용하여 JSON 개체를 출력 스트림에 작성할 수 있습니다.
- javax.json.stream.JsonParser: 이는 풀 파서로 작동하며 JSON 개체를 읽는 데 대한 스트리밍 지원을 제공합니다.
- javax.json.stream.JsonGenerator: 이를 사용하여 JSON 개체를 스트리밍 방식으로 출력 소스에 작성할 수 있습니다.
- javax.json.Json: 이는 JSON 처리 개체를 생성하기 위한 팩토리 클래스입니다. 이 클래스는 이러한 개체를 만들기 위한 가장 일반적으로 사용되는 메서드와 해당 팩토리를 제공합니다. 팩토리 클래스는 이러한 개체를 만들기 위한 모든 다양한 방법을 제공합니다.
- javax.json.JsonObject: JsonObject는 변경 불가능한 JSON 개체 값을 나타냅니다.
간단한 프로그램과 함께 Java JSON API의 사용법을 살펴보겠습니다. employee.txt라는 파일에 저장된 JSON 개체가 있습니다;
{
"id":123,
"name":"Pankaj Kumar",
"permanent":true,
"address":{
"street":"El Camino Real",
"city":"San Jose",
"zipcode":95014
},
"phoneNumbers":[9988664422, 1234567890],
"role":"Developer"
}
위의 JSON 형식을 나타내는 자바 빈 클래스가 있습니다.
package com.journaldev.model;
import java.util.Arrays;
public class Employee {
private int id;
private String name;
private boolean permanent;
private Address address;
private long[] phoneNumbers;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isPermanent() {
return permanent;
}
public void setPermanent(boolean permanent) {
this.permanent = permanent;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long[] getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(long[] phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("***** Employee Details *****\n");
sb.append("ID="+getId()+"\n");
sb.append("Name="+getName()+"\n");
sb.append("Permanent="+isPermanent()+"\n");
sb.append("Role="+getRole()+"\n");
sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"\n");
sb.append("Address="+getAddress());
sb.append("\n*****************************");
return sb.toString();
}
}
package com.journaldev.model;
public class Address {
private String street;
private String city;
private int zipcode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
@Override
public String toString(){
return getStreet() + ", "+getCity()+", "+getZipcode();
}
}
I have overridden the toString() method to return human readable String representation that we will use in our JSON implementation classes.
Java JSON 읽기 예제
package com.journaldev.json;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONReader {
public static final String JSON_FILE="employee.txt";
public static void main(String[] args) throws IOException {
InputStream fis = new FileInputStream(JSON_FILE);
// JsonReader 객체 생성
JsonReader jsonReader = Json.createReader(fis);
/**
* We can create JsonReader from Factory also
JsonReaderFactory factory = Json.createReaderFactory(null);
jsonReader = factory.createReader(fis);
*/
// JsonReader에서 JsonObject 가져오기
JsonObject jsonObject = jsonReader.readObject();
// IO 리소스와 JsonReader를 닫을 수 있음
jsonReader.close();
fis.close();
// JsonObject에서 데이터를 가져와서 Employee bean 생성
Employee emp = new Employee();
emp.setId(jsonObject.getInt("id"));
emp.setName(jsonObject.getString("name"));
emp.setPermanent(jsonObject.getBoolean("permanent"));
emp.setRole(jsonObject.getString("role"));
// json에서 배열 읽기
JsonArray jsonArray = jsonObject.getJsonArray("phoneNumbers");
long[] numbers = new long[jsonArray.size()];
int index = 0;
for(JsonValue value : jsonArray){
numbers[index++] = Long.parseLong(value.toString());
}
emp.setPhoneNumbers(numbers);
// json 객체에서 내부 객체 읽기
JsonObject innerJsonObject = jsonObject.getJsonObject("address");
Address address = new Address();
address.setStreet(innerJsonObject.getString("street"));
address.setCity(innerJsonObject.getString("city"));
address.setZipcode(innerJsonObject.getInt("zipcode"));
emp.setAddress(address);
// employee bean 정보 출력
System.out.println(emp);
}
}
구현은 간단하며 HashMap에서 매개변수를 가져오는 것과 유사한 느낌입니다. JsonReaderFactory는 팩토리 디자인 패턴을 구현합니다. 위의 프로그램을 실행하면 다음과 같은 출력이 나옵니다.
***** Employee Details *****
ID=123
Name=Pankaj Kumar
Permanent=true
Role=Developer
Phone Numbers=[9988664422, 1234567890]
Address=El Camino Real, San Jose, 95014
*****************************
Java JSON 쓰기 예제
package com.journaldev.json;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonWriter;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONWriter {
public static void main(String[] args) throws FileNotFoundException {
Employee emp = createEmployee();
JsonObjectBuilder empBuilder = Json.createObjectBuilder();
JsonObjectBuilder addressBuilder = Json.createObjectBuilder();
JsonArrayBuilder phoneNumBuilder = Json.createArrayBuilder();
for (long phone : emp.getPhoneNumbers()) {
phoneNumBuilder.add(phone);
}
addressBuilder.add("street", emp.getAddress().getStreet())
.add("city", emp.getAddress().getCity())
.add("zipcode", emp.getAddress().getZipcode());
empBuilder.add("id", emp.getId())
.add("name", emp.getName())
.add("permanent", emp.isPermanent())
.add("role", emp.getRole());
empBuilder.add("phoneNumbers", phoneNumBuilder);
empBuilder.add("address", addressBuilder);
JsonObject empJsonObject = empBuilder.build();
System.out.println("Employee JSON String\n"+empJsonObject);
// 파일에 쓰기
OutputStream os = new FileOutputStream("emp.txt");
JsonWriter jsonWriter = Json.createWriter(os);
/**
* We can get JsonWriter from JsonWriterFactory also
JsonWriterFactory factory = Json.createWriterFactory(null);
jsonWriter = factory.createWriter(os);
*/
jsonWriter.writeObject(empJsonObject);
jsonWriter.close();
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
return emp;
}
}
위의 애플리케이션을 실행하면 다음과 같은 응답을 받습니다:
Employee JSON String
{"id":100,"name":"David","permanent":false,"role":"Manager","phoneNumbers":[123456,987654],"address":{"street":"BTM 1st Stage","city":"Bangalore","zipcode":560100}}
JSON 객체는 emp.txt 파일에도 저장됩니다. JsonObjectBuilder는 빌더 패턴을 구현하여 사용하기 매우 쉽습니다.
Java JSON 파서 예제
Java JsonParser는 pull 파서이며 next() 메서드를 사용하여 다음 요소를 읽습니다. 이 메서드는 Event 객체를 반환합니다. javax.json.stream.JsonParser.Event
는 타입 안전하고 사용하기 쉬운 Enum입니다. 우리는 switch case에서 자바 빈 속성을 설정하는 데 사용할 수 있습니다.
package com.journaldev.json;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.journaldev.model.Address;
import com.journaldev.model.Employee;
public class EmployeeJSONParser {
public static final String FILE_NAME = "employee.txt";
public static void main(String[] args) throws IOException {
InputStream fis = new FileInputStream(FILE_NAME);
JsonParser jsonParser = Json.createParser(fis);
/**
* We can create JsonParser from JsonParserFactory also with below code
* JsonParserFactory factory = Json.createParserFactory(null);
* jsonParser = factory.createParser(fis);
*/
Employee emp = new Employee();
Address address = new Address();
String keyName = null;
List phoneNums = new ArrayList();
while (jsonParser.hasNext()) {
Event event = jsonParser.next();
switch (event) {
case KEY_NAME:
keyName = jsonParser.getString();
break;
case VALUE_STRING:
setStringValues(emp, address, keyName, jsonParser.getString());
break;
case VALUE_NUMBER:
setNumberValues(emp, address, keyName, jsonParser.getLong(), phoneNums);
break;
case VALUE_FALSE:
setBooleanValues(emp, address, keyName, false);
break;
case VALUE_TRUE:
setBooleanValues(emp, address, keyName, true);
break;
case VALUE_NULL:
// 아무것도 설정하지 않음
break;
default:
// 다른 이벤트를 찾지 않음
}
}
emp.setAddress(address);
long[] nums = new long[phoneNums.size()];
int index = 0;
for(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
System.out.println(emp);
// 리소스를 닫음
fis.close();
jsonParser.close();
}
private static void setNumberValues(Employee emp, Address address,
String keyName, long value, List phoneNums) {
switch(keyName){
case "zipcode":
address.setZipcode((int)value);
break;
case "id":
emp.setId((int) value);
break;
case "phoneNumbers":
phoneNums.add(value);
break;
default:
System.out.println("Unknown element with key="+keyName);
}
}
private static void setBooleanValues(Employee emp, Address address,
String key, boolean value) {
if("permanent".equals(key)){
emp.setPermanent(value);
}else{
System.out.println("Unknown element with key="+key);
}
}
private static void setStringValues(Employee emp, Address address,
String key, String value) {
switch(key){
case "name":
emp.setName(value);
break;
case "role":
emp.setRole(value);
break;
case "city":
address.setCity(value);
break;
case "street":
address.setStreet(value);
break;
default:
System.out.println("Unknown Key="+key);
}
}
}
데이터를 파싱하는 로직을 작성해야 할 때 주요 복잡성이 발생하며 때로는 복잡해질 수 있습니다. JsonReader와 동일한 파일을 읽기 때문에 출력은 EmployeeJsonReader 프로그램과 동일합니다.
Java JsonGenerator 예제
package com.journaldev.json;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import com.journaldev.model.Employee;
public class EmployeeJSONGenerator {
public static void main(String[] args) throws IOException {
OutputStream fos = new FileOutputStream("emp_stream.txt");
JsonGenerator jsonGenerator = Json.createGenerator(fos);
/**
* We can get JsonGenerator from Factory class also
* JsonGeneratorFactory factory = Json.createGeneratorFactory(null);
* jsonGenerator = factory.createGenerator(fos);
*/
Employee emp = EmployeeJSONWriter.createEmployee();
jsonGenerator.writeStartObject(); // {
jsonGenerator.write("id", emp.getId()); // "id":123
jsonGenerator.write("name", emp.getName());
jsonGenerator.write("role", emp.getRole());
jsonGenerator.write("permanent", emp.isPermanent());
jsonGenerator.writeStartObject("address") //start of address object
.write("street", emp.getAddress().getStreet())
.write("city",emp.getAddress().getCity())
.write("zipcode",emp.getAddress().getZipcode())
.writeEnd(); //end of address object
jsonGenerator.writeStartArray("phoneNumbers"); //start of phone num array
for(long num : emp.getPhoneNumbers()){
jsonGenerator.write(num);
}
jsonGenerator.writeEnd(); // end of phone num array
jsonGenerator.writeEnd(); // }
jsonGenerator.close();
}
}
JsonGenerator는 사용하기 매우 쉽고 대용량 데이터에 대해 좋은 성능을 제공합니다. 이것으로 Java JSON 처리 API에 대해 배웠습니다. Java JSON 파서, 읽기 및 쓰기 예제에 대해 알아보았습니다. 아래 링크에서 자바 프로젝트를 다운로드하여 실험해 볼 수 있습니다.
참고 자료: JSONLint – JSON 데이터를 유효성 검사하는 훌륭한 웹 도구 JSON 처리 참조 구현 JSR353 JCP 페이지
Source:
https://www.digitalocean.com/community/tutorials/java-json-example