专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  池化技术:让真实业务效率飙升的利器 ·  昨天  
芋道源码  ·  Nginx性能优化的几个方法 ·  昨天  
芋道源码  ·  SpringBoot + Tika ... ·  昨天  
芋道源码  ·  确保数据安全!使用Spring Boot ... ·  2 天前  
51好读  ›  专栏  ›  ImportNew

Jackson 通过自定义注解来控制 json key 的格式

ImportNew  · 公众号  · Java  · 2017-01-10 19:58

正文

(点击 上方公众号 ,可快速关注)


来源:Rollen Holt,

www.cnblogs.com/rollenholt/p/5406573.html

如有好文章投稿,请点击 → 这里了解详情


最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换。而这个替换过程是需要依赖一个第三方的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是一模一样的。


而Jackson也给我们提供了注解:@JsonProperty注解来帮助我们重命名生成的json的key。但是他这个重命名并不是很灵活,因为他只能固定的重命名为某一个「确定的」值,而不能容许我们做一些额外的操作。


所以在这种情况下,我打算自定义一个注解,因为业务场景相关,我们的注解定义如下:


@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface Dimension {

String valueType();

}


假设我们的json的key的生成规则如下:


  • valueType()的值为“id”时,json key追加后缀“_id”


  • valueType()的值为”code”时,json key追加后缀“_code”


这个时候我们就可以使用Jackson提供给我们强大的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 jsonToBean(String json, Class 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;

}







请到「今天看啥」查看全文