今天,念念不忘一件事... ✅FastJson在调用JSON#toJSONString时,如何截取 ...

打印 上一主题 下一主题

主题 1014|帖子 1014|积分 3042

项目里 前后端页面的http请求 及 dubbo服务间的RPC调用,返回值类型统一是一个Result,其结构如下。
  1. @Data
  2. public class Result<T> implements Serializable {
  3.     private static final long serialVersionUID = 1L;
  4.     /**
  5.      * 返回处理消息
  6.      */
  7.     private String message = "操作成功!";
  8.     /**
  9.      * 返回代码
  10.      */
  11.     private Integer code = 0;
  12.     /**
  13.      * 返回数据对象 data
  14.      */
  15.     @Getter
  16.     private T data;
  17. }
复制代码
 
项目的RPC使用的是dubbo。我们在项目中定义了一个公用的DubboTraceFilter。这个Filter会将接口方法返回值 Result对象 打印到log文件里。序列化方式用的是 fastjson 的 JSON#toJSONString。
 
背景介绍完毕。接下来说我要解决的事情。
注意到Result的data字段。它是泛型T的实例,就是说,这个data会是任意类型的数据。
从log里看,当data里是集合数据,例如,分页查询的场景,打印出来的log会超长。
这导致日志量很大,同时,这种无用的日志刷屏,也不利于我们排查问题。
 
简言之,看下面两段json串(为便于阅读,进行了格式化),希望log里出现后者。
  1. {
  2.     "message": "成功",
  3.     "code": 200,
  4.     "result": ["0memob92142f2-ad8a-4812-913e-002f8f9d1894", "1memo77d4ad82-078f-4f73-a26e-c5302a596042", "2memoa69185c2-670d-480b-b1d2-19fd1326ecd5", "3memoee5d13a7-83bd-4430-a4b0-198e65201dc7", "4memo519d9d69-a27f-4864-8dd4-889ada1790a3", "5memo85034936-564b-41d8-94f0-ff1ac7be8d92", "6memoa22d4b20-828a-4ac5-a3fe-461283fc4154", "7memo7b2b8880-80b2-41f8-93d9-553467287e13", "8memo55afe9f2-e6b5-481c-9978-773fb5ff0f14", "9memoa5a92ffd-4e72-42f1-8d81-7221d2f371a3"],
  5.     "timestamp": 1666961782888
  6. }
复制代码
  1. {
  2.     "code": 200,
  3.     "message": "成功",
  4.     "result": "["0memob92142f2-ad8a-4812-913e-002f8f9d1894","1memo77d4ad82-078f-4f73-a26e-c5302a596042","2memoa6...",
  5.     "timestamp": 1666961782888
  6. }
复制代码
 
 
那么,如何解决这个痛点?
我相信,找开发组里的任何一位同学,他都能解决。改DubboTraceFilter里的代码就行了,对序列化的json串进行相关截取。
 
而我想说什么呢?
 
一劳永逸!
程序里有还有其他地方也存在通过 JSON#toJSONString(Result) 打印log的代码。 难道逐个改吗?
所以,有没有简单的办法,改一处就全改了。
 
世上无易事,用心求精进。只要不放弃,办法就会有。
解决办法是 利用 com.alibaba.fastjson.serializer.ObjectSerializer 和 com.alibaba.fastjson.annotation.JSONField 。
 
首先,通过实现ObjectSerializer接口来自定义一个序列化器: StringAbbreviatingSerializer
  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.serializer.JSONSerializer;
  3. import com.alibaba.fastjson.serializer.ObjectSerializer;
  4. import org.apache.commons.lang.StringUtils;
  5. import java.io.IOException;
  6. import java.lang.reflect.Type;
  7. public class StringAbbreviatingSerializer implements ObjectSerializer {
  8.     /**
  9.      *
  10.      * @param serializer
  11.      * @param object field的值
  12.      * @param fieldName field的name
  13.      * @param fieldType field的类型,如java.lang.String
  14.      * @param features
  15.      * @throws IOException
  16.      */
  17.     @Override
  18.     public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
  19.         serializer.write( StringUtils.abbreviate(JSON.toJSONString(object),100));
  20.     }
  21. }
复制代码
View Code 
然后,使用com.alibaba.fastjson.annotation.JSONField 注解。
  1.     @JSONField(serializeUsing = StringAbbreviatingSerializer.class)
  2.     private T data;
复制代码
 
完了吗?我要补充——一并重写Result的toString方法。彻底一劳永逸。
  1. @Data
  2. public class Result<T> implements Serializable {
  3.     。。。。
  4.    
  5.     @Override
  6.     public String toString() {
  7.         return JSON.toJSONString(this);
  8.     }
  9. }
复制代码
 
 
要说明的是,加上这个注解后,对Result的实际值并不会有影响(包括http请求和dubbo调用,亲测)。所以,放心用,放心去序列化。妈妈再也不用担心我的日志爆屏了。
 
 
over!
 
 
附:
使用fastjson提供的接口实现自定义的编解码器

在项目开发中经常会遇到一些业务需要对某些数据进行特殊的定制化处理,fastjson为我们提供了接口可以用于实现自定义的编解码器来完成我们的业务要求。
ObjectSerializer和ObjectDeserializer分别是fastjson的编码器和解码器接口。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

盛世宏图

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表