🍃 Spring

@JsonProperty 사용법에 대한 모든 것

loose 2023. 7. 9. 21:24
반응형

필드명이 다를 때 치환 용도

	@GetMapping("/changeCamelCase1")
    public String changeCamelCase1(@RequestBody Student1 student) {
        System.out.println(student.myAge + "--" + student.myName);
        return "ok";
    }

    @GetMapping("/changeCamelCase2")
    public String changeCamelCase2(@RequestBody Student2 student) {

        System.out.println(student.myAge + "--" + student.myName);
        return "ok";
    }

    @Data
    public static class Student1 {
        @JsonProperty("my_name")
        private String myName;

        @JsonProperty("my_age")
        private String myAge;
    }

    @Data
    @JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
    public static class Student2 {
        private String myName;
        private String myAge;
    }

다른 블로그에 나와 있듯이 my_name이라는 Client 영역에서 넘어오는 Snake Case 문법을 Camel Case로 바꾸는 데에 사용할 수 있다.

 

메소드 레벨에서 사용하기

	@GetMapping("/using-in-method")
    public ResponseEntity<MyObject> usingInMethod() throws JsonProcessingException {
        MyObject myObject = new MyObject();

        ObjectMapper mapper = new ObjectMapper();
        // Serialize Java object and change @JsonProperty at the method level to reflect in the resulting JSON data.
        String json = mapper.writeValueAsString(myObject);
        // "{\"myName\":\"stir\"}" Json Data created in Java Object is deserializing to Json
        MyObject obj = mapper.readValue(json, MyObject.class);

        System.out.println(obj.myName());

        return ResponseEntity.ok(myObject);
    }
    public static class MyObject {
        String myName;
        @JsonProperty
        public String myName() {
            return "stir";
        }
    }

 

myName이라는 메소드 위에 @JsonProperty를 사용했다. 

그리고 MyObject를 ResponseEntity나 ResponseBody를 통해서 Java Object를 JSON 형태로 치환해주는 과정에서 myName 메소드 이름이 JSON 값으로 들어가게 된다.

{
	"myName" : "stir"
}

@JsonProperty가 필요 없는 경우

	@Data
    public static class Student {
        @JsonProperty
        private String myName;
    }

 

위에서 @JsonProperty 기능은 myName 값을 Json으로 변환시켜주는 기능을 한다.

하지만 위와 같이 필드에 @JsonProperty를 사용하면서 어노테이션 안에 아무것도 안적어주는 경우는 지워주는 것이 좋다.

왜냐면 오류가 나지는 않지만 기능의 중복이 발생하기 때문이다.

예를들어 Student를 Controller에서 @ResponseBody로 Return하는 경우에 알아서 JSON으로 변환해주기 때문이다.

필드에서 사용하는 @JsonProperty는 필드 네임 매칭이 아니라면 쓸 일이 없다.

그러므로 위와 같이 사용하는 코드는 냄새나는 코드로 간주하고 지워서 사용하는 것이 좋다.

 

무분별한 JsonProperty 사용을 하려면 Enum으로 관리하기

 	enum DevType{

        MOBILE(Constant.MOBILE),
        WEB(Constant.WEB),
        SERVER(Constant.SERVER);

        public static class Constant {
            public static final String MOBILE = "안드로이드";
            public static final String WEB = "스프링";
            public static final String SERVER = "리눅스";
        }
        private String krName;

        private DevType(String krName){
            this.krName = krName;
        }
        public String getKrName() {
            return krName;
        }
    }
    public class MyObject3 {
        @JsonProperty(DevType.Constant.MOBILE)
        private String android;
        @JsonProperty(DevType.Constant.WEB)
        private String spring;

    }

@JsonProperty를 이곳 저곳에 사용하다보면 무분별하게 사용되기도 하고 값을 한 곳에서 관리하기가 힘들 수 있다.

그럴 때는 위처럼 Enum을 사용하면 좀 더 중앙 집중적으로 관리할 수 있다.

 

 

하지만 Enum은 보통 그룹화된 상수를 관리하기 위한 목적으로 쓰이기 때문에 위와 같이 단순히 1:1 매칭으로만 쓰이는 상수라면 단순한 Final을 써도 상관없다.

만약에 변경해야 될 값이 여러개고 비슷한 값들이 모여있는 그룹화된 상수를 활용하려면 아래와 같이 사용하면 좋다.

Enum으로 Group으로 묶여진 상수 관리하기

  	enum DevType{

        MOBILE(new SpecificDev[]{
                SpecificDev.IOS, SpecificDev.ANDROID
        }),
        WEB(new SpecificDev[]{
                SpecificDev.SPRING, SpecificDev.NODE, SpecificDev.PYTHON
        }),
        SERVER(new SpecificDev[]{
                SpecificDev.LINUX, SpecificDev.WINDOWS
        });

        enum SpecificDev{
            ANDROID(Constant.ANDROID),
            IOS(Constant.IOS),
            SPRING(Constant.SPRING),
            NODE(Constant.NODE),
            PYTHON(Constant.PYTHON),
            LINUX(Constant.LINUX),
            WINDOWS(Constant.WINDOWS);

            private String krName;
            SpecificDev(String krName) {
                this.krName = krName;
            }

            public String getKrName() {
                return krName;
            }
            public static class Constant {
                public static final String ANDROID = "안드로이드";
                public static final String IOS = "아이폰";
                public static final String SPRING = "스프링";
                public static final String NODE = "노드";
                public static final String PYTHON = "파이썬";
                public static final String LINUX = "리눅스";
                public static final String WINDOWS = "윈도우";
            }
        }
        
        private SpecificDev[] specificDev;

        private DevType(SpecificDev[] specificDevs){
            this.specificDev = specificDevs;
        }
        public SpecificDev[] getSpecificDev() {
            return specificDev;
        }
    }
    public class MyObject3 {
        @JsonProperty(DevType.SpecificDev.Constant.ANDROID)
        private String android;
        @JsonProperty(DevType.SpecificDev.Constant.SPRING)
        private String spring;
    }

중분류, 소분류 형태로 만든 것이라고 보면 된다.

위와 같은 방식으로 @JsonProperty를 좀 더 효율적으로 관리할 수 있다.

 

728x90