티스토리 뷰
728x90
반응형
Overview
JSON 형태의 데이터를 java에서 활용할 수 있도록 데이터 타입을 변환해주는 기능
build.gradle
dependencies {
implementation group:'com.fasterxml.jackson.core', name:'jackson-databind', version:'2.12.3'
}
readValue()
- Text JSON → Object, JSON 데이터를 Java 객체로 역직렬화하는 데 사용
- Object Mapper는 객체의 default 생성자가 필요
//json = {"name":"KKK","age":34,"cars":[{"name":"K5","car_number":"0161","TYPE":"SUV"},{"name":"K7","car_number":"1111","TYPE":"SEDAN"}]}
ObjectMapper objectMapper = new ObjectMapper();
var objectUser = objectMapper.readValue(json, User.class);
System.out.println(objectUser); //User{name='KKK', age=34}
- 문자열, 파일, URL, InputStream 등 여러 형식의 입력을 받을 수 있다.
<T> T readValue(Reader src, Class<T> valueType) throws IOException;
<T> T readValue(String content, Class<T> valueType) throws IOException;
<T> T readValue(InputStream src, Class<T> valueType) throws IOException;
<T> T readValue(URL src, Class<T> valueType) throws IOException;
<T> T readValue(File src, Class<T> valueType) throws IOException;
writeValueAsString()
- Object → Text json, Java 객체를 JSON 문자열로 직렬화하는 데 사용
- Object Mapper가 객체의 get method를 활용
- 객체에서 get method 이외의 method명에 get을 붙이면 안됨
ObjectMapper objectMapper = new ObjectMapper();
User user = new User("snail", 34);
String json = objectMapper.writeValueAsString(user);
System.out.println(json); //{"name":"snail", "age":34}
readTree()
- JSON 데이터를 트리 구조로 파싱하려면 readTree() 메서드를 사용
- JSON 문자열을 전달받아 해당 문자열을 트리 구조로 파싱한 JsonNode를 반환
- JsonNode를 사용하여 JSON 데이터를 탐색하고 필요한 작업을 수행
JsonNode
- JsonNode는 JSON 데이터를 표현하는 데 사용되는 트리 형식의 데이터 구조
- 이 트리를 사용하여 JSON 데이터를 탐색하고 쿼리하거나 수정할 수 있다.
- JsonNode에는 여러 가지 하위 클래스가 있으며, ObjectNode(객체), ArrayNode(배열), TextNode(텍스트), NumericNode(숫자), BooleanNode(부울) 등이 있다.
//json = {"name":"KKK","age":34,"cars":[{"name":"K5","car_number":"0161","TYPE":"SUV"},{"name":"K7","car_number":"1111","TYPE":"SEDAN"}]}
JsonNode jsonNode = objectMapper.readTree(json); //JSON -> Object
String _name = jsonNode.get("name").asText();
int _age = jsonNode.get("age").asInt();
System.out.println("name : " + _name);
System.out.println("age : " + _age);
String _carList = jsonNode.get("cars").asText(); //null
JsonNode cars = jsonNode.get("cars"); // 객체에 접근할 때는 노드 객체로 불러와서
ArrayNode arrayNode = (ArrayNode)cars; // ArrayNode 변환
List<Car> _cars = objectMapper.convertValue(arrayNode, new TypeReference<List<Car>>() {}); // object mapper 로 형변환
System.out.println(_cars);
//[Car{name='K5', carNumber='0161', type='SUV'}, Car{name='K7', carNumber='1111', type='SEDAN'}]
ObjectNode objectNode = (ObjectNode) jsonNode;
objectNode.put("name", "ghm"); //json 값 변경
objectNode.put("age", 37);
System.out.println(objectNode.toPrettyString());
/*
{
"name" : "ghm",
"age" : 37,
"cars" : [ {
"name" : "K5",
"car_number" : "0161",
"TYPE" : "SUV"
}, {
"name" : "K7",
"car_number" : "1111",
"TYPE" : "SEDAN"
} ]
}
*/
get() 메서드
- 존재하는 필드: 해당 JsonNode 반환
- 존재하지 않는 필드: null 반환
- null이 반환될 수 있기 때문에 NullPointerException을 방지하려면 직접 null 체크가 필요
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "{ \"name\": \"Alice\", \"age\": 25 }";
JsonNode rootNode = mapper.readTree(json);
JsonNode nameNode = rootNode.get("name"); // 존재하는 필드
JsonNode missingNode = rootNode.get("nonExistentKey"); // 없는 필드
System.out.println(nameNode.asText()); // 출력: Alice
System.out.println(missingNode); // 출력: null
// 아래 코드는 NullPointerException 발생 가능
// System.out.println(missingNode.asText());
}
}
path() 메서드
- 존재하는 필드: 해당 JsonNode 반환
- 존재하지 않는 필드: MissingNode 반환 (null이 아님)
- MissingNode는 안전하게 asText(), asLong() 같은 변환 메서드를 사용할 수 있음
- null을 반환하지 않으므로 NullPointerException 위험 없음
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "{ \"name\": \"Alice\", \"age\": 25 }";
JsonNode rootNode = mapper.readTree(json);
JsonNode nameNode = rootNode.path("name"); // 존재하는 필드
JsonNode missingNode = rootNode.path("nonExistentKey"); // 없는 필드
System.out.println(nameNode.asText()); // 출력: Alice
System.out.println(missingNode.asText()); // 출력: "" (빈 문자열)
// 안전하게 숫자로 변환 가능
System.out.println(missingNode.asLong()); // 출력: 0
}
}
setSerializationInclusion()
- 직렬화 시에 null 값이 포함되는지 여부를 설정하는 데 사용
- JsonInclude.Include 열거형은 Jackson에서 직렬화 시에 어떤 필드를 포함할지를 결정하는 데 사용
- ALWAYS: 항상 필드를 포함합니다. 즉, null 값을 가진 필드도 포함됩니다.
- NON_NULL: null 값을 가진 필드를 제외하고 나머지는 포함합니다.
- NON_ABSENT: Optional과 같은 컨테이너 타입의 필드에서 null 값이 아닌 경우에만 포함합니다.
- NON_EMPTY: null, 빈 문자열, 빈 컬렉션 등을 제외하고 나머지는 포함합니다.
- NON_DEFAULT: 기본값과 같지 않은 필드만 포함합니다. (주로 기본값이 null인 경우에 유용합니다)
- USE_DEFAULTS: 기본 설정을 따릅니다. (기본값)
ObjectMapper objectMapper2 = new ObjectMapper();
objectMapper2.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Car car3 = new Car();
car3.setName("GV80");
car3.setCarNumber("");
System.out.println("car3 : " + car3); //String carNumber = "", String type = null, int createdYear = 0
String car3Json = objectMapper2.writeValueAsString(car3);
System.out.println("car3Json : " + car3Json);
//car3Json : {"name":"GV80","createdYear":0,"car_number":""}
SerializationFeature
Jackson에서 직렬화 시의 동작을 설정하는 데 사용
- FAIL_ON_EMPTY_BEANS: 빈 객체를 직렬화할 때 실패합니다.
- FAIL_ON_SELF_REFERENCES: 객체에 대한 자기 참조를 발견하면 실패합니다.
- INDENT_OUTPUT: 출력을 들여쓰기하여 가독성을 높입니다.
- WRITE_NULL_MAP_VALUES: null 값을 가진 맵 필드를 포함합니다.
- WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED: 단일 요소 배열을 배열이 아닌 단일 값으로 직렬화합니다.
- WRITE_ENUMS_USING_TO_STRING: 열거형을 직렬화할 때 toString() 메서드를 사용합니다.
- WRITE_ENUMS_USING_INDEX: 열거형을 직렬화할 때 인덱스 값을 사용합니다.
DeserializationFeature
Jackson에서 역직렬화 시의 동작을 설정하는 데 사용
- ACCEPT_EMPTY_STRING_AS_NULL_OBJECT: 빈 문자열("")을 null 객체로 처리합니다.
- ACCEPT_SINGLE_VALUE_AS_ARRAY: 단일 값을 배열로 처리합니다.
- FAIL_ON_UNKNOWN_PROPERTIES: 알려지지 않은 속성이 있는 경우 역직렬화를 실패시킵니다.
- FAIL_ON_NULL_FOR_PRIMITIVES: 원시(primitive) 타입 필드에 null 값을 만나면 역직렬화를 실패시킵니다.
- UNWRAP_SINGLE_VALUE_ARRAYS: 단일 값을 포함하는 배열을 단일 값으로 처리합니다.
- READ_ENUMS_USING_TO_STRING: 열거형을 직렬화할 때 toString() 메서드를 사용하여 읽습니다.
- READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE: 알려지지 않은 열거형 값이 있을 때 기본값을 사용하여 역직렬화합니다.
objectMapper2.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); //객체에 없는 Json 필드는 역직렬화 무시
String json2 = "{\"name\":\"GV80\",\"unknown\":\"9999\"}";
Car car3Deserialization = objectMapper2.readValue(json2, Car.class);
System.out.println("car3Deserialization : " + car3Deserialization);
//Car{name='GV80', carNumber='null', type='null', createdYear=0}
MissingNode.getInstance()
- 존재하지 않는 필드를 나타냅니다.
- JSON에서 해당 필드가 아예 존재하지 않을 때 사용됩니다.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.MissingNode;
public class JacksonExample {
public static void main(String[] args) {
JsonNode missingNode = MissingNode.getInstance();
System.out.println(missingNode); // 출력:
System.out.println(missingNode.isMissingNode()); // 출력: true
}
}
MissingNode.path("anyKey")의 동작 원리
- MissingNode.getInstance()는 Jackson에서 존재하지 않는 필드를 표현하는 객체입니다.
- MissingNode에서 .path("key")를 호출하면 항상 새로운 MissingNode를 반환합니다.
- 출력값은 비어 있는 값처럼 보이며, .isMissingNode()를 호출하면 true를 반환합니다.
NullNode.getInstance()
- null 값을 나타내는 노드입니다.
- JSON에서 {"key": null} 같은 경우에 해당합니다.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.NullNode;
public class JacksonExample {
public static void main(String[] args) {
JsonNode nullNode = NullNode.getInstance();
System.out.println(nullNode); // 출력: null
System.out.println(nullNode.isNull()); // 출력: true
}
}
ObjectNode에서 빈 객체 생성
- JSON {}처럼 비어 있는 객체를 표현하고 싶다면 ObjectNode를 사용
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class JacksonExample {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode emptyObject = mapper.createObjectNode();
System.out.println(emptyObject); // 출력: {}
}
}
https://github.com/FasterXML/jackson-docs
https://www.baeldung.com/jackson
https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/latest/index.html
728x90
반응형
'Java' 카테고리의 다른 글
동작 파라미터화 코드 전달하기 (0) | 2023.06.21 |
---|---|
Optional (0) | 2022.09.18 |
Primitive vs Wrapper Class (0) | 2022.03.20 |
Functional Programming (0) | 2022.03.14 |
Lambda Expression (0) | 2020.09.14 |
반응형
300x250