现象
定义了一个类,使用JSONField指定toString后的key值(主要想用来解决首字母大写问题)
@Data
@EqualsAndHashCode(callSuper = false)
public class ShareholderInOutVO extends BasePojo {
@JSONField(name = "Period")
private String Period;
……
}
通过JSONObject.toJSONString(obj)后结果为:
修改实体类:
@Data
@EqualsAndHashCode(callSuper = false)
public class ShareholderInOutVO extends BasePojo {
@JSONField(name = "Period")
private String period;
……
}
通过JSONObject.toJSONString(obj)后结果为:
分析
几个主要的断点:
JSONSerializer类
public ObjectSerializer getObjectWriter(Class<?> clazz) {
……
if (Proxy.isProxyClass(clazz)) {
config.put(clazz, config.createJavaBeanSerializer(clazz));
} else {
config.put(clazz, config.createJavaBeanSerializer(clazz));
}
}
writer = config.get(clazz);
}
return writer;
}
SerializeConfig类
ASMSerializerFactory类
最终定位到TypeUtils.computeGetters方法
public static List<FieldInfo> computeGetters(Class<?> clazz, Map<String, String> aliasMap, boolean sorted) {
Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<String, FieldInfo>();
for (Method method : clazz.getMethods()) {
String methodName = method.getName();
if (Modifier.isStatic(method.getModifiers())) {
continue;
}
if (method.getReturnType().equals(Void.TYPE)) {
continue;
}
if (method.getParameterTypes().length != 0) {
continue;
}
if (method.getReturnType() == ClassLoader.class) {
continue;
}
if (method.getName().equals("getMetaClass")
&& method.getReturnType().getName().equals("groovy.lang.MetaClass")) {
continue;
}
JSONField annotation = method.getAnnotation(JSONField.class);
if (annotation == null) {
annotation = getSupperMethodAnnotation(clazz, method);
}
if (annotation != null) {
if (!annotation.serialize()) {
continue;
}
if (annotation.name().length() != 0) {
String propertyName = annotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, null));
continue;
}
}
if (methodName.startsWith("get")) {
if (methodName.length() < 4) {
continue;
}
if (methodName.equals("getClass")) {
continue;
}
char c3 = methodName.charAt(3);
String propertyName;
if (Character.isUpperCase(c3)) {
if (compatibleWithJavaBean) {
propertyName = Introspector.decapitalize(methodName.substring(3));
} else {
// flag: 根据get方法拿到属性名后把首字母变成小写了
propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
}
} else if (c3 == '_') {
propertyName = methodName.substring(4);
} else if (c3 == 'f') {
propertyName = methodName.substring(3);
} else {
continue;
}
boolean ignore = isJSONTypeIgnore(clazz, propertyName);
if (ignore) {
continue;
}
// flag:根据全小写的属性名获取类中的Field,导致无法获取
Field field = ParserConfig.getField(clazz, propertyName);
// flag:以下获取@JSONField定义被忽略
if (field != null) {
JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
if (fieldAnnotation != null) {
if (!fieldAnnotation.serialize()) {
continue;
}
if (fieldAnnotation.name().length() != 0) {
propertyName = fieldAnnotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
}
}
}
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, field));
}
if (methodName.startsWith("is")) {
if (methodName.length() < 3) {
continue;
}
char c2 = methodName.charAt(2);
String propertyName;
if (Character.isUpperCase(c2)) {
if (compatibleWithJavaBean) {
propertyName = Introspector.decapitalize(methodName.substring(2));
} else {
propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
}
} else if (c2 == '_') {
propertyName = methodName.substring(3);
} else if (c2 == 'f') {
propertyName = methodName.substring(2);
} else {
continue;
}
Field field = ParserConfig.getField(clazz, propertyName);
if (field == null) {
field = ParserConfig.getField(clazz, methodName);
}
if (field != null) {
JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
if (fieldAnnotation != null) {
if (!fieldAnnotation.serialize()) {
continue;
}
if (fieldAnnotation.name().length() != 0) {
propertyName = fieldAnnotation.name();
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
}
}
}
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, field));
}
}
for (Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
String propertyName = field.getName();
if (fieldAnnotation != null) {
if (!fieldAnnotation.serialize()) {
continue;
}
if (fieldAnnotation.name().length() != 0) {
propertyName = fieldAnnotation.name();
}
}
if (aliasMap != null) {
propertyName = aliasMap.get(propertyName);
if (propertyName == null) {
continue;
}
}
if (!fieldInfoMap.containsKey(propertyName)) {
fieldInfoMap.put(propertyName, new FieldInfo(propertyName, null, field));
}
}
List<FieldInfo> fieldInfoList = new ArrayList<FieldInfo>();
boolean containsAll = false;
String[] orders = null;
JSONType annotation = clazz.getAnnotation(JSONType.class);
if (annotation != null) {
orders = annotation.orders();
if (orders != null && orders.length == fieldInfoMap.size()) {
containsAll = true;
for (String item : orders) {
if (!fieldInfoMap.containsKey(item)) {
containsAll = false;
break;
}
}
} else {
containsAll = false;
}
}
if (containsAll) {
for (String item : orders) {
FieldInfo fieldInfo = fieldInfoMap.get(item);
fieldInfoList.add(fieldInfo);
}
} else {
for (FieldInfo fieldInfo : fieldInfoMap.values()) {
fieldInfoList.add(fieldInfo);
}
if (sorted) {
Collections.sort(fieldInfoList);
}
}
return fieldInfoList;
}
解决思路
- 属性名改成”period”
- 不使用lombok的get/set方法,并将@JSONField写在get方法上:
总结
Java规范【属性小驼峰命名】很重要