Jackson 은 사용자 정의 주 해 를 통 해 json key 의 형식 을 제어 합 니 다.

11772 단어
Jackson 은 사용자 정의 주 해 를 통 해 json key 의 형식 을 제어 합 니 다.
최근 에 제 게 필요 한 것 은 Bean 의 특정한 필드 의 값 을 교체 해 야 한 다 는 것 입 니 다.이 교체 과정 은 제3자 의 dubbo 서비스 에 의존 해 야 한다.이 전환 기능 을 더욱 통용 시 키 기 위해 우 리 는 다음 과 같은 방식 을 채택 했다.
  • client 단 은 사용자 정의 주석 (@Dimension 으로 가정) 을 사용 하여 Bean 의 모든 '특수 필드'
  • 을 표시 합 니 다.
  • client 단 은 bean 을 json 형식 으로 바 꾸 었 으 나 이 변환 과정의 요 구 는 이러한 특수 한 필드 에 대응 하 는 json 의 key 는 일정한 형식 에 부합 되 어야 하 며, 이 형식 은 표 시 된 @Dimension 주해
  • 에 의존 해 야 한다.
  • 그리고 client 단 은 dubbo RPC 서 비 스 를 통 해 json 을 server 단 에 던 지고 server 는 json 분석 을 한 다음 에 교 체 된 json 을 client 단 에 던 진 다음 에 client 단 은 받 은 json 을 이전의 Bean 대상 의 인 스 턴 스 로 되 돌려 줍 니 다.

  • 먼저 bean 을 json 으로 바 꾸 는 것 을 살 펴 보 겠 습 니 다. 보통 특별한 요구 가 없 으 면 우 리 는 모두:
     /**
     * Object   POJO,    Collection   。
     *      Null,   "null".
     *         ,   "[]".
     *
     * @param object the object to json
     * @return toJson result
     */
        public String toJson(Object object) {
            try {
                return mapper.writeValueAsString(object);
            } catch (IOException e) {
                LOGGER.error("write to json string error:" + object, e);
                return null;
            }
        }

    이것 은 기본 적 인 상황 입 니 다. 생 성 된 json 의 key 와 해당 하 는 Bean 의 filed name 은 똑 같 습 니 다.
    잭 슨 도 우리 에 게 주 해 를 제공 했다. @JsonProperty 주 해 는 우리 가 생 성 된 제 이 슨 의 키 를 바 꾸 는 데 도움 을 주 었 다.그러나 그의 이름 을 바 꾸 는 것 은 그다지 유연 하지 않다. 왜냐하면 그 는 '확실한' 값 으로 만 고정 적 으로 이름 을 바 꿀 수 있 을 뿐 우리 가 추가 적 인 조작 을 하 는 것 을 허용 할 수 없 기 때문이다.
    그래서 이런 상황 에서 저 는 주 해 를 사용자 정의 하려 고 합 니 다. 업무 장면 과 관련 되 기 때문에 저희 의 주 해 는 다음 과 같 습 니 다.
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface Dimension {
        String valueType();
    }

    우리 제 이 슨 의 key 생 성 규칙 은 다음 과 같다 고 가정 합 니 다.
  • value Type () 의 값 이 "id" 일 때 json key 는 접미사 " id"
  • 을 추가 합 니 다.
  • value Type () 의 값 이 "code" 일 때 json key 는 접미사 " code"
  • 을 추가 합 니 다.
    이 럴 때 우 리 는 잭 슨 을 사용 하여 우리 에 게 강력 한 JacksonAnnotationIntrospector 종 류 를 제공 할 수 있다.
    import com.google.common.base.Preconditions;
    import org.codehaus.jackson.Version;
    import org.codehaus.jackson.Versioned;
    import org.codehaus.jackson.map.introspect.AnnotatedField;
    import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
    import org.codehaus.jackson.util.VersionUtil;
    
    import java.lang.annotation.Annotation;
    
    import static com.google.common.base.Strings.isNullOrEmpty;
    
    /**
     * @author rollenholt
     */
    public class DimensionFieldSerializer extends JacksonAnnotationIntrospector implements Versioned {
    
        @Override
        public Version version() {
            return VersionUtil.versionFor(getClass());
        }
    
    
        @Override
        public boolean isHandled(Annotation ann) {
            Class<?> cls = ann.annotationType();
            if (Dimension.class == cls) {
                return true;
            }
            return super.isHandled(ann);
        }
    
    
        @Override
        public String findSerializablePropertyName(AnnotatedField af) {
            return getPropertyName(af);
        }
    
        @Override
        public String findDeserializablePropertyName(AnnotatedField af) {
            return getPropertyName(af);
        }
    
        private String getPropertyName(AnnotatedField af) {
            Dimension annotation = af.getAnnotation(Dimension.class);
            if (annotation != null) {
                String valueType = annotation.valueType();
                Preconditions.checkArgument(!isNullOrEmpty(valueType), "@Dimension    valudType    ");
                if (valueType.equalsIgnoreCase("id")) {
                    return af.getName() + "_id";
                }
                if (valueType.equalsIgnoreCase("code")) {
                    return af.getName() + "_code";
                }
            }
            return af.getName();
        }
    
    }
    

    또한 위의 코드 를 터치 하고 우리 의 기능 을 검증 하기 위해 다음 과 같은 코드 가 있 습 니 다.
    /**
     * @author rollenholt
     */
    public class DimensionAdapterHelper {
    
        private final static ObjectMapper objectMapper = new ObjectMapper();
    
        static {
            AnnotationIntrospector dimensionFieldSerializer = new DimensionFieldSerializer();
            objectMapper.setAnnotationIntrospector(dimensionFieldSerializer);
        }
    
        public static String beanToJson(Object object) {
            StringWriter sw = new StringWriter();
            try {
                objectMapper.writeValue(sw, object);
                return sw.toString();
            } catch (IOException e) {
                throw Throwables.propagate(e);
            }
        }
    
        public static <T> T jsonToBean(String json, Class<T> clazz) {
            try {
                return (T) objectMapper.readValue(json, clazz);
            } catch (IOException e) {
                throw Throwables.propagate(e);
            }
        }
    
    
        public static class Type {
            private String code;
    
            @Dimension(valueType = "id")
            private String description;
    
            @Dimension(valueType = "code")
            private String value;
    
            public Type() {
            }
    
            public Type(String code, String description, String value) {
                super();
                this.code = code;
                this.description = description;
                this.value = value;
            }
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }
    
            public String getDescription() {
                return description;
            }
    
            public void setDescription(String description) {
                this.description = description;
            }
    
            public String getValue() {
                return value;
            }
    
            public void setValue(String value) {
                this.value = value;
            }
    
            @Override
            public String toString() {
                return ToStringBuilder.reflectionToString(this);
            }
        }
    
        public static void main(String[] args) {
            Type t = new Type("a", "b", "c");
            String json = beanToJson(t);
            System.out.println(json);
            Type type = jsonToBean(json, Type.class);
            System.out.println(type);
    
        }
    
    
    }

    실행 후 출력 결 과 는:
    {"code":"a","description_id":"b","value_code":"c"}
    DimensionAdapterHelper$Type@2cb4c3ab[code=a,description=b,value=c]

    그래도 우리 의 기대 에 부합 하 는 편 이다.
    server 엔 드 가 json 문자열 의 key 를 어떻게 바 꾸 는 지 에 대해 간단히 말 하면 key 는 일정한 형식 이 있 기 때문에 json 을 옮 겨 다 니 는 모든 key 를 되 돌 릴 수 있 습 니 다. 어떤 key - value 가 처리 해 야 하 는 지 알 수 있 습 니 다.자바 에서 편리 한 제 이 슨 을 재 귀 하 는 방법 에 대해 서 는 간단 하 다.만약 모두 가 필요 하 다 고 느낀다 면, 나 는 뒤에 쓰 고 있다.
    참고 자료
  • http://unmi.cc/customize-jackson-annotation-and-disable-specific-annotation/ 비록 우 리 는 이 글 을 사용 하 는 방법 이
  • 은 아니 지만

    좋은 웹페이지 즐겨찾기