Jackson @JsonSetter 활용

이번 시간엔 Java의 Jackson json library 중 @JsonSetter라는 annotation을 어떻게 사용해야 할지 알아보겠다.

public class Person {

  private String name;
  private Integer age = -1;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return age;
  }

  @JsonSetter(value = "age", nulls = Nulls.SKIP)
  public void setAge(Integer age) {
    this.age = age + 10;
  }
}

위와 같이 Person 클래스를 정의해보자. 필드는 간단하게 nameage 두개로 구성되어 있다. 사실 있는 값을 그대로 받아온다면 굳이 @JsonSetter는 사용할 필요가 없다. 하지만 만약 우리가 값에 어떤 특정 조작을 해야 한다면, 저 annotation은 매우 유용하다고 할 수 있다. 위의 경우엔 입력된 나이 값에 10을 더해서 값을 세팅하도록 해놨다.

여기서 신경써야할 몇가지 코너 케이스들이 있다.

  • Input json에 age 필드가 없을 경우
    • 이 경우엔 기본적으로 annotate되어있는 이 함수가 실행되지 않는다. 그래서 위에서 age=-1로 기본 값을 설정해 놓은 것이다.
  • age==null인 경우
    • 이 경우는 별도의 지시가 없으면 함수가 실행이 된다. 그런데 대부분의 경우 null이나 필드가 없는 경우나 동일시하는게 맞기 때문에, 이번 예제에서는 nulls=Nulls.SKIP을 사용함으로써, 값이 null일때는 함수를 실행하지 않도록 하였다. 그럼 결국 기본값인 -1을 유지할 것이다.

마지막으로 unit test를 써서 잘 동작하는지 확인해보자.

@Test
public void testDeserialization() throws IOException {
  String jsonStr = "{\n"
      + "  \"name\": \"Jacob\",\n"
      + "  \"age\": null\n"
      + "}";
  ObjectMapper mapper = new ObjectMapper();
  Person person = mapper.readValue(jsonStr, Person.class);
  assertEquals("Jacob", person.getName());
  assertEquals(-1L, person.getAge().longValue());

  jsonStr = "{\n"
      + "  \"name\": \"Jacob\",\n"
      + "  \"age\": 30\n"
      + "}";
  person = mapper.readValue(jsonStr, Person.class);
  assertEquals(40L, person.getAge().longValue());
}

[Java] instanceOf 활용

오늘 소개할 instanceOf라는 것은 특정 포인터가 특정 type인지를 살펴보는 방식이다. 예를 들면,

object instanceOf SomeClass
/* 
만약 object가 SomeClass 타입일 경우 true를 리턴하고, 
그렇지 않으면 false를 리턴한다. 
여기서 SomeClass는 제가 예를 위해 가정한 클래스고, 
아무 클래스라도 가능하다. 
*/

특히나 Java에서 Data Object를 많이 다루게 되면 필수로 사용하게 되는 기본 스킬이라고 할 수 있다.

Spark DataFrame 크기 계산하기

Broadcast join이 적합한지 궁금할 때, 아니면 executor resource를 얼마나 써야하는지 궁금할 때, 실제 DataFrame의 크기를 계산해 보는것은 매우 중요하다.

물론 아쉽게도 정확하게 그 DataFrame이 어떤 크기를 갖는지는 disk에 저장을 해봐야 알겠지만, 다행히도 Spark에서 좋은 API를 제공한다. 아래의 코드는 Scala Spark를 가정했다.

import org.apache.spark.util.SizeEstimator

SizeEstimator.estimate(df)

// res4_1: Long = 27739224L

위와 같이 SizeEstimator를 사용하면 해당 df가 어느 정도 크기를 갖는지 알려준다. 위에서 df의 크기는 약 27.7MB이다.

위의 코드를 production에서 돌릴 수는 없기 때문에, prototyping을 할 때 써보기를 추천한다.