JSON

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

字号+ 作者:H5之家 来源:H5之家 2017-12-06 10:05 我要评论( )

最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换。而这个替换过程是需要依赖一个第三方的dubbo服务的。

原文出处: Rollen Holt

最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换。而这个替换过程是需要依赖一个第三方的dubbo服务的。为了使得这个转换功能更加的通用,我们采用了下面的方式:

我们先来看看把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> 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对需要处理了。关于如何在Java中递归便利Json,这个比较简单。如果大家觉的有需要,我后面在写。

    参考资料
  • 虽然我们并没有使用这个文章的做法

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • jsonlint:python的json数据验证库

      jsonlint:python的json数据验证库

      2017-12-06 09:00

    • PHP如何处理JAVA过来的接口和PHP返回给Javascript的JSON字符串

      PHP如何处理JAVA过来的接口和PHP返回给Javascript的JSON字符串

      2017-12-05 10:12

    • 千锋教育视频教程

      千锋教育视频教程

      2017-12-04 10:00

    • JSON 與XML比較

      JSON 與XML比較

      2017-12-04 09:03

    网友点评