最近我這邊有一個需求就是須要把Bean中的某一些特殊字段的值進行替換。而這個替換過程是須要依賴一個第三方的dubbo服務的。爲了使得這個轉換功能更加的通用,咱們採用了下面的方式:java
@Dimension
)標記Bean中全部的「特殊字段」@Dimension
註解咱們先來看看把bean轉爲json,通常沒有特殊要求的話,咱們都是: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是如出一轍的。數組
而Jackson也給咱們提供了註解:@JsonProperty
註解來幫助咱們重命名生成的json的key。可是他這個重命名並非很靈活,由於他只能固定的重命名爲某一個「肯定的」值,而不能允許咱們作一些額外的操做。app
因此在這種狀況下,我打算自定義一個註解,由於業務場景相關,咱們的註解定義以下:ide
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Dimension { String valueType(); }
假設咱們的json的key的生成規則以下:ui
這個時候咱們就可使用Jackson提供給咱們強大的JacksonAnnotationIntrospector
類了。this
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(); } }
同時爲了觸發上面的代碼,以及爲了驗證咱們的功能,咱們有以下的代碼:google
/** * @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
{"code":"a","description_id":"b","value_code":"c"} DimensionAdapterHelper$Type@2cb4c3ab[code=a,description=b,value=c]
還算是很符合咱們的指望的。server
至於server端是如何替換json字符串的key的那塊,簡單的說一下,由於key有必定的格式,因此能夠遞歸遍歷json的全部key,就能夠拿到有哪些key-value對須要處理了。關於如何在Java中遞歸便利Json,這個比較簡單。若是你們覺的有須要,我後面在寫。
http://unmi.cc/customize-jackson-annotation-and-disable-specific-annotation/ 雖然咱們並無使用這個文章的作法