본문 바로가기
Programing/Spring

Spring에서 Json을 파라메터로 넘겼을 때 어떻게 객체로 받을 수 있을까?

by Tomining 2017. 7. 21.
먼저 "Spring에서 Request 또는 Response로 전달되는 파라메터 정보를 Controller에서 어떻게 Java 객체로 받을 수 있을까”라는 의문이 먼저 들었다.

예를 들면 http://test.domain.com/test?no=1234&id=testId 라는 url이 있다고 가정하자.
@RequestMapping(value=“test”, method = RequestMethod.GET)
public void test(@RequestParam(“id”) String id, @RequestParam(“no”) int no) {
    // 구현로직
}
아마 Controller의 메소드는 위 처럼 구현되어 있을 것이다.
여기서 id와 no는 어떻게 각각 String과 int 형으로 변환이 되는 것일까?

Spring에서 HttpMessageConverter가 그 역할을 담당하고 있다.
Request나 Respons 내에는 모두 Text 형식이라고 할 수 있다. 이를 Java 자료형으로 변환해 주는 역할을 한다.

MessageConverter에는 몇 가지 종류가 있다.
  • ByteArrayHttpMessageConverter
  • StringHttpMessageConverter
  • FormHttpMessageConverter
  • SourceHttpMessageConverter
  • Jaxb2RootElementHttpMessageConverter
  • MarshallingHttpMessageConverter
  • MappingJackson2HttpMessageConverter

이름만 봐도 직관적으로 어떤 자료형을 담당하는지 잘 알 수 있다. 이 외에도 Spring은 더 많은 MessageConverter를 지원한다.

여기서는 JSON 형태의 데이터를 POJO 객체로 변환하는 역할을 담당하는 MappingJackson2HttpMessageConverter를 살펴보자.
아래는 Spring 내에 구현되어 있는 MappingJackson2HttpMessageConverter 코드이다.
public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
    private String jsonPrefix;

    public MappingJackson2HttpMessageConverter() {
        this(Jackson2ObjectMapperBuilder.json().build());
    }

    public MappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper, new MediaType[]{MediaType.APPLICATION_JSON_UTF8, new MediaType("application", "*+json", DEFAULT_CHARSET)});
    }

    public void setJsonPrefix(String jsonPrefix) {
        this.jsonPrefix = jsonPrefix;
    }

    public void setPrefixJson(boolean prefixJson) {
        this.jsonPrefix = prefixJson ? ")]}', " : null;
    }

    protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
        if (this.jsonPrefix != null) {
            generator.writeRaw(this.jsonPrefix);
        }

        String jsonpFunction = object instanceof MappingJacksonValue ? ((MappingJacksonValue)object).getJsonpFunction() : null;
        if (jsonpFunction != null) {
            generator.writeRaw("/**/");
            generator.writeRaw(jsonpFunction + "(");
        }

    }

    protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
        String jsonpFunction = object instanceof MappingJacksonValue ? ((MappingJacksonValue)object).getJsonpFunction() : null;
        if (jsonpFunction != null) {
            generator.writeRaw(");");
        }

    }
}

생성자에서 Jackson 라이브러리의 ObjectMapper 클래스를 생성해서 가지고 있다.(build 메소드)
이를 이용하여 JSON을 객체로 변환하는 것이다.
ObjectMapper를 생성할 때, 몇 가지 Confiuration을 설정할 수 있다.(아래 코드는 그냥 예제이다.)
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);

Enum 타입의 속성은 JSON 변환시 name 값을 사용한다거나 존재하지 않는 Property인 경우 어떻게 처리할지에 대한 설정을 할 수 있다. 아래 두 Enum 코드를 살펴보면 더 많은 속성을 확인할 수 있다.(친절하게 주석에 그 역할을 잘 설명하고 있다.)
  • SerializationFeature
  • DeserializationFeature

JSON을 다루다 보면 날짜 포멧이나 UnknownProperty 처리에 삽질을 하는 경우가 있는데. 다음 기회에 삽질기도 한 번 포스팅 해 보아야 겠다.

참고