[Java] ObjectMapper

Soo·2023년 11월 10일
post-thumbnail

Java class 내용을 확인하려는 과정에서 데이터 타입이 맞지 않아서 에러가 발생했었다. 그 과정에서 내용물 parsing이 필요했고, 그러기 위해서는 Jackson에서 제공해주는 ObjectMapper를 사용할 수 있다는 것을 알게 되었다.

💡 ObjectMapper

  • JSON 컨텐츠를 Java 객체로 deserialization 하거나 Java 객체를 JSON으로 serialization 할 때 사용하는 Jackson 라이브러리의 클래스이다.
  • ObjectMapper는 생성비용이 비싸기 때문에 bean/static으로 처리하는 것이 좋다.

🛠️ ObjectMapper 사용법

기존에 다음과 같은 클래스가 있다고 가정한다. 이 때 주의해야 할 점은 객체로 만들 클래스에서 getter와 default 생성자 생성을 꼭 확인해야 한다.

@Getter // Object -> String 문자열로 바꿀 때 필요
class Car {
private String name;
private String color;

public Car(String name, String color) {
	this.name = name; 
    this color = color;
  }
  
  public Car() { // String 문자열 -> Object로 바꿀 때 필요
  	this.name = null;
    this.color = null;
  }
}

1. Java Object ➡️ String 문자열

  • Java 객체를 JSON으로 serialization 하기 위해서는 ObjectMapper의 writeValue() 메소드를 사용한다.
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("sonata", "white");

String text = carMapper.WriteValueAsString(car); 
// {"name": "sontata", "color": "white"}
  • 다시 한번 주의해야 할 점은 JSON으로 직렬화 시킬 클래스에 Getter가 존재해야만 한다.
  • Jackson 라이브러리는 Getter와 Setter를 이용해 prefix를 잘라내고 맨 앞을 소문자로 만드는 것으로 필드를 식별한다.
  • 만약 serialization할 클래스에 Getter가 존재하지 않으면 클래스에서 필드를 식별하지 못하고 결국 값을 가져오지 못하기 때문에 에러가 발생한다.

2. String 문자열 ➡️ Java Object

  • JSON 파일을 Java 객체로 deserialization하기 위해서 ObjectMapper의 readValue() 메소드를 사용한다.
Car carObject = carMapper.readValue(text, Car.class);
// Car{name = 'sonata', color = 'white'}
  • 위와 같이 파라미터로 JSON 형태의 문자열 or 객체와 deserialization시킬 클래스를 넣어줘야 한다.
  • deserialization시킬 클래스에 JSON을 파싱하 결과를 전달할 생성자가 있어야 한다.
  • 기본 생성자를 이용하는 방법, 생성자에 Jackson 라이브러리의 @JsonCreator 어노테이션을 쓰는 등 다양한 방법들이 있다.

만약 다음과 같은 에러가 발생한다면, 클래스에 적절한 생성자가 없는 경우이기 때문에 이와 같은 에러가 발생한다면, 생성자가 있는지 다시 한번 확인해보자!

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `Car` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"name":"sonata","color":"white"}"; line: 1, column: 2]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1209)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1415)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
	at ObjectMapperEx.main(ObjectMapperEx.java:22)

❗️ 주의해야할 점은

Car 클래스에서 내가 만드는 메소드나 생성자 이름에 get이라는 단어가 들어가지 않도록 한다.

profile
Soogineer's Devlog

0개의 댓글