fastJson遇到的坑之造轮子实现按优先级将实体类的属性与属性值拼串
按优先级将实体类的属性与属性值拼串
起因
之前写过一个公共方法,实现对一个表的存储,但是今天报了个测试问题。排查问题的时候发现,如果不把所有字段的值打印出来,不便于问题的定位。但是由于我们的实体类是通过代码生成工具自动生成的,并且没有重写toString。
第一个坑
我们的实体中不光有表中的字段,还有一些别的方法,方法中有查询sql,如果直接用 fastJosn 转json串的话,会死循环,一直会去执行方法中的查询语句。
第二个坑
fastJson中可以指定 includes,测试发现指定 includes 可以解决死循环,但是问题又来了,我们的实体的中字段的首字母是大写,fastJson获取不到属性值
SimplePropertyPreFilter propertyPreFilter = new SimplePropertyPreFilter();Set<String> includes = propertyPreFilter.getIncludes();
造轮子
通过反射获取实体的属性和值
代码实现
/* @description 将实体按照 属性名:值 拼串,并用逗号隔开* @author HelloWorld* @create 2023/4/5 09:02* @param studentSchema* @return java.lang.String*/public String getInfo(StudentSchema studentSchema) {PropertyDescriptor[] propertyDescriptors;try {propertyDescriptors = Introspector.getBeanInfo(studentSchema.getClass()).getPropertyDescriptors();} catch (IntrospectionException e) {log.error("实体解析异常,只打印简单信息", e);return getSimpleInfo(studentSchema);}String resultStr = Stream.iterate(0, n -> n + 1).limit(propertyDescriptors.length - 1).map(index -> {PropertyDescriptor propertyDescriptor = propertyDescriptors[index];String propertyName = propertyDescriptor.getName();Object propertyValue;try {propertyValue = propertyDescriptor.getReadMethod().invoke(studentSchema);} catch (Exception e) {log.error(String.format("获取属性值-%s异常", propertyName), e);propertyValue = null;}return String.format("%s: %s", propertyName, propertyValue);}).collect(Collectors.joining(", "));return String.format("StudentSchema: {%s}", resultStr);}/* @description 返回简要信息串* @author HelloWorld* @create 2023/4/5 09:04* @param studentSchema* @return java.lang.String*/public String getSimpleInfo(StudentSchema studentSchema) {return String.format("StudentSchema: {name: %s, idType: %s, idNo: %s}",studentSchema.getName(),studentSchema.getIdType(),studentSchema.getIdNo());}
效果
StudentSchema: {age: 19, birthday: 2001-08-01, class: class com.wy.other.printSchema.StudentSchema, className: null, country: China, happy: null, idNo: 4112991729102121, idType: 00, makeDate: Wed Apr 05 09:05:13 CST 2023, makeTime: 09:05:13, modifyDate: Wed Apr 05 09:05:13 CST 2023, modifyTime: 09:05:13, name: 李白, score: null}
缺陷
拼接的信息有 class字段
第一次优化
- 排除掉不想展示的字段
- 如果是Date类型的字段, yyyy-MM-dd 格式化
代码
private static final Set<String> excludes = new HashSet<>(Arrays.asList("class", "modifyDate", "modifyTime"));/* @description 将实体按照 属性名:值 拼串,并用逗号隔开* @author HelloWorld* @create 2023/4/5 09:02* @param studentSchema* @return java.lang.String*/public String getInfo(StudentSchema studentSchema) {PropertyDescriptor[] propertyDescriptors;try {propertyDescriptors = Introspector.getBeanInfo(studentSchema.getClass()).getPropertyDescriptors();} catch (IntrospectionException e) {log.error("实体解析异常,只打印简单信息", e);return getSimpleInfo(studentSchema);}String resultStr = Stream.iterate(0, n -> n + 1).limit(propertyDescriptors.length - 1).map(index -> {PropertyDescriptor propertyDescriptor = propertyDescriptors[index];String propertyName = propertyDescriptor.getName();if (excludes.contains(propertyName)) {return null;}Object propertyValue;try {propertyValue = propertyDescriptor.getReadMethod().invoke(studentSchema);propertyValue = propertyValue instanceof Date ? DateUtil.format(DateUtil.parse(propertyValue.toString()), "yyyy-MM-dd") : propertyValue;} catch (Exception e) {log.error(String.format("获取属性值-%s异常", propertyName), e);propertyValue = null;}return String.format("%s: %s", propertyName, propertyValue);}).filter(StrUtil::isNotBlank).collect(Collectors.joining(", "));return String.format("StudentSchema: {%s}", resultStr);}/* @description 返回简要信息串* @author HelloWorld* @create 2023/4/5 09:04* @param studentSchema* @return java.lang.String*/public String getSimpleInfo(StudentSchema studentSchema) {return String.format("StudentSchema: {name: %s, idType: %s, idNo: %s}",studentSchema.getName(),studentSchema.getIdType(),studentSchema.getIdNo());}
效果
StudentSchema: {age: 19, birthday: 2001-08-01, className: null, country: China, happy: null, idNo: 4112991729102121, idType: 00, makeDate: 2023-04-05, makeTime: 09:36:36, name: 李白, score: null}
第二次优化
- 按照指定的优先级 排练字段
- 调整代码结构
代码
private static final Set<String> excludes = new HashSet<>(Arrays.asList("class", "modifyDate", "modifyTime"));private static final List<String> priorityList;static {priorityList = Arrays.asList("Name", "IdNo", "Age", "ClassName").stream().map(str -> str.substring(0, 1).toLowerCase() + str.substring(1)).sorted(((o1, o2) -> -1)).collect(Collectors.toList());}/* @description 将实体按照 属性名:值 拼串,并用逗号隔开* @author HelloWorld* @create 2023/4/5 09:02* @param studentSchema* @return java.lang.String*/public String getInfo(StudentSchema studentSchema) {PropertyDescriptor[] propertyDescriptors;try {propertyDescriptors = Introspector.getBeanInfo(studentSchema.getClass()).getPropertyDescriptors();} catch (IntrospectionException e) {log.error("实体解析异常,只打印简单信息", e);return getSimpleInfo(studentSchema);}String resultStr = Arrays.stream(propertyDescriptors).map(PropertyDescriptor::getName).filter(name -> !excludes.contains(name)).map(name -> {Object value;try {value = new PropertyDescriptor(name, studentSchema.getClass()).getReadMethod().invoke(studentSchema);} catch (Exception e) {log.error(String.format("获取属性值-%s异常", name), e);return null;}if (value instanceof Date) {value = ((Date) value).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();}return name + ": " + value;}).filter(StrUtil::isNotBlank).sorted(((o1, o2) -> {o1 = o1.substring(0, o1.lastIndexOf(":"));o2 = o2.substring(0, o2.lastIndexOf(":"));return priorityList.indexOf(o2) - priorityList.indexOf(o1);})).collect(Collectors.joining(", "));return String.format("StudentSchema: {%s}", resultStr);}/* @description 返回简要信息串* @author HelloWorld* @create 2023/4/5 09:04* @param studentSchema* @return java.lang.String*/public String getSimpleInfo(StudentSchema studentSchema) {return String.format("StudentSchema: {name: %s, idType: %s, idNo: %s}",studentSchema.getName(),studentSchema.getIdType(),studentSchema.getIdNo());}
效果
StudentSchema: {name: 李白, idNo: 4112991729102121, age: 19, className: 六年级, birthday: 2001-08-01, country: China, happy: null, idType: 00, makeDate: 2023-04-05, makeTime: 10:11:28, score: null, sex: null}
全部代码
StudentSchema
package com.wy.other.printSchema;import java.io.StringReader;
import java.math.BigDecimal;
import java.util.Date;/* @author HelloWorld* @create 2023/4/4 22:51* @email helloworld.dng@gmail.com*/public class StudentSchema {private String Name;private String IdType;private String IdNo;private String ClassName;private String Country;private Integer Age;private String Birthday;private String Happy;private String Sex;private BigDecimal Score;private Date MakeDate;private String MakeTime;private Date ModifyDate;private String ModifyTime;public String getName() {return Name;}public void setName(String name) {Name = name;}public String getIdType() {return IdType;}public void setIdType(String idType) {IdType = idType;}public String getIdNo() {return IdNo;}public void setIdNo(String idNo) {IdNo = idNo;}public String getClassName() {return ClassName;}public void setClassName(String className) {ClassName = className;}public String getCountry() {return Country;}public void setCountry(String country) {Country = country;}public Integer getAge() {return Age;}public void setAge(Integer age) {Age = age;}public String getBirthday() {return Birthday;}public void setBirthday(String birthday) {Birthday = birthday;}public String getHappy() {return Happy;}public void setHappy(String happy) {Happy = happy;}public String getSex() {return Sex;}public void setSex(String sex) {Sex = sex;}public BigDecimal getScore() {return Score;}public void setScore(BigDecimal score) {Score = score;}public Date getMakeDate() {return MakeDate;}public void setMakeDate(Date makeDate) {MakeDate = makeDate;}public String getMakeTime() {return MakeTime;}public void setMakeTime(String makeTime) {MakeTime = makeTime;}public Date getModifyDate() {return ModifyDate;}public void setModifyDate(Date modifyDate) {ModifyDate = modifyDate;}public String getModifyTime() {return ModifyTime;}public void setModifyTime(String modifyTime) {ModifyTime = modifyTime;}
}
package com.wy.other.printSchema;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;/* @author HelloWorld* @create 2023/4/4 22:54* @email helloworld.dng@gmail.com*/
@Slf4j
public class Print {private static final Set<String> excludes = new HashSet<>(Arrays.asList("class", "modifyDate", "modifyTime"));private static final List<String> priorityList;static {priorityList = Arrays.asList("Name", "IdNo", "Age", "ClassName").stream().map(str -> str.substring(0, 1).toLowerCase() + str.substring(1)).sorted(((o1, o2) -> -1)).collect(Collectors.toList());}/* @description 将实体按照 属性名:值 拼串,并用逗号隔开* @author HelloWorld* @create 2023/4/5 09:02* @param studentSchema* @return java.lang.String*/public String getInfo(StudentSchema studentSchema) {PropertyDescriptor[] propertyDescriptors;try {propertyDescriptors = Introspector.getBeanInfo(studentSchema.getClass()).getPropertyDescriptors();} catch (IntrospectionException e) {log.error("实体解析异常,只打印简单信息", e);return getSimpleInfo(studentSchema);}String resultStr = Arrays.stream(propertyDescriptors).map(PropertyDescriptor::getName).filter(name -> !excludes.contains(name)).map(name -> {Object value;try {value = new PropertyDescriptor(name, studentSchema.getClass()).getReadMethod().invoke(studentSchema);} catch (Exception e) {log.error(String.format("获取属性值-%s异常", name), e);return null;}if (value instanceof Date) {value = ((Date) value).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();}return name + ": " + value;}).filter(StrUtil::isNotBlank).sorted(((o1, o2) -> {o1 = o1.substring(0, o1.lastIndexOf(":"));o2 = o2.substring(0, o2.lastIndexOf(":"));return priorityList.indexOf(o2) - priorityList.indexOf(o1);})).collect(Collectors.joining(", "));return String.format("StudentSchema: {%s}", resultStr);}/* @description 返回简要信息串* @author HelloWorld* @create 2023/4/5 09:04* @param studentSchema* @return java.lang.String*/public String getSimpleInfo(StudentSchema studentSchema) {return String.format("StudentSchema: {name: %s, idType: %s, idNo: %s}",studentSchema.getName(),studentSchema.getIdType(),studentSchema.getIdNo());}public static void main(String[] args) {Print print = new Print();System.out.println(print.getInfo(getTestData()));}private static StudentSchema getTestData() {StudentSchema studentSchema = new StudentSchema();studentSchema.setName("李白");studentSchema.setAge(19);studentSchema.setBirthday("2001-08-01");studentSchema.setCountry("China");studentSchema.setIdNo("4112991729102121");studentSchema.setIdType("00");studentSchema.setMakeDate(new Date());studentSchema.setMakeTime(DateUtil.formatTime(new Date()));studentSchema.setModifyDate(new Date());studentSchema.setModifyTime(DateUtil.formatTime(new Date()));studentSchema.setClassName("六年级");return studentSchema;}
}