所以自己动手,基于fastjson的源代码构造了单独的javabean的序列化器。
fastjson版本为1.2.7
MetaJsonUtil.getJSONString(bean)
MetaJsonUtil 类
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializeConfig; /** * fastJson不支持对象中私有属性的转换 * Created by 魔力鸟 on 2015-10-15. */ public final class MetaJsonUtil { /** * 获取对象对应属性数据组成的JSON对象 * @param target * @return */ public static JSONObject getJSONObject(Object target) { return JSON.parSEObject(getJSONString(target)); } /** * 获取对象对应属性数据组成的字符串 * @param target * @return */ public static String getJSONString(Object target) { if (target != null) { SerializeConfig globalInstance = SerializeConfig.getGlobalInstance(); globalInstance.put(target.getClass(),new MetaBeanSerializer(target.getClass())); return JSON.toJSONString(target,globalInstance); }else{ return "{}"; } } }用到的2个类:
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.serializer.*; import com.alibaba.fastjson.util.FieldInfo; import com.alibaba.fastjson.util.TypeUtils; import org.springframework.util.ReflectionUtils; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * fastjson不支持私有或保护属性的序列化,使用本类支持。 * 注意:仅实现了序列化,未实现反序列化 * Created by 张三丰 on 2015-10-14. */ public class MetaBeanSerializer extends JavaBeanSerializer { private final FieldSerializer[] getters ; private final FieldSerializer[] sortedGetters; private int features = 0; public MetaBeanSerializer(Class<?> clazz) { this(clazz,null); } public MetaBeanSerializer(Class<?> clazz,Map<String,String> aliasMap) { super(clazz,aliasMap); this.features = TypeUtils.getSerializeFeatures(clazz); { List<FieldSerializer> getterList = new ArrayList<FieldSerializer>(); List<FieldInfo> fieldInfoList = MetaTypeUtils.computeGetters(clazz,aliasMap,false); for (FieldInfo fieldInfo : fieldInfoList) { getterList.add(createFieldSerializer(fieldInfo)); } getters = getterList.toArray(new FieldSerializer[getterList.size()]); } { List<FieldSerializer> getterList = new ArrayList<FieldSerializer>(); List<FieldInfo> fieldInfoList = MetaTypeUtils.computeGetters(clazz,true); for (FieldInfo fieldInfo : fieldInfoList) { getterList.add(createFieldSerializer(fieldInfo)); } sortedGetters = getterList.toArray(new FieldSerializer[getterList.size()]); } } public void write(JSONSerializer serializer,Object object,Object fieldName,Type fieldType,int features) throws IOException { SerializeWriter out = serializer.getWriter(); if (object == null) { out.writeNull(); return; } if (writeReference(serializer,object,features)) { return; } final FieldSerializer[] getters; if (out.isEnabled(SerializerFeature.SortField)) { getters = this.sortedGetters; } else { getters = this.getters; } SerialContext parent = serializer.getContext(); serializer.setContext(parent,fieldName,this.features,features); final boolean writeAsArray = isWriteAsArray(serializer); try { final char startSeperator = writeAsArray ? '[' : '{'; final char endSeperator = writeAsArray ? ']' : '}'; out.append(startSeperator); if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.incrementIndent(); serializer.println(); } boolean commaFlag = false; if (isWriteClassName(serializer,fieldType,fieldName)) { Class<?> objClass = object.getClass(); if (objClass != fieldType) { out.writeFieldName(JSON.DEFAULT_TYPE_KEY); serializer.write(object.getClass()); commaFlag = true; } } char seperator = commaFlag ? ',' : '\0'; char newSeperator = FilterUtils.writeBefore(serializer,seperator); commaFlag = newSeperator == ','; for (int i = 0; i < getters.length; ++i) { FieldSerializer fieldSerializer = getters[i]; Field field = fieldSerializer.getField(); if (serializer.isEnabled(SerializerFeature.SkipTransientField)) { if (field != null) { if (Modifier.isTransient(field.getModifiers())) { continue; } } } if (serializer.isEnabled(SerializerFeature.IgnoreNonFieldGetter)) { if (field == null) { continue; } } if (!FilterUtils.applyName(serializer,fieldSerializer.getName())) { continue; } if (!FilterUtils.applyLabel(serializer,fieldSerializer.getLabel())) { continue; } Object propertyValue = fieldSerializer.getPropertyValue(object); if (!FilterUtils.apply(serializer,fieldSerializer.getName(),propertyValue)) { continue; } String key = FilterUtils.processKey(serializer,propertyValue); Object originalValue = propertyValue; propertyValue = FilterUtils.processValue(serializer,propertyValue); if (propertyValue == null && !writeAsArray) { if ((!fieldSerializer.isWriteNull()) && (!serializer.isEnabled(SerializerFeature.WriteMapNullValue))) { continue; } } if (propertyValue != null && serializer.isEnabled(SerializerFeature.NotWriteDefaultValue)) { Field field1 = ReflectionUtils.findField(FieldSerializer.class,"fieldInfo"); ReflectionUtils.makeAccessible(field1); Class<?> fieldCLass = ((FieldInfo)ReflectionUtils.getField(field1,fieldSerializer)).getFieldClass(); if (fieldCLass == byte.class && propertyValue instanceof Byte && ((Byte) propertyValue).byteValue() == 0) { continue; } else if (fieldCLass == short.class && propertyValue instanceof Short && ((Short) propertyValue).shortValue() == 0) { continue; } else if (fieldCLass == int.class && propertyValue instanceof Integer && ((Integer) propertyValue).intValue() == 0) { continue; } else if (fieldCLass == long.class && propertyValue instanceof Long && ((Long) propertyValue).longValue() == 0L) { continue; } else if (fieldCLass == float.class && propertyValue instanceof Float && ((Float) propertyValue).floatValue() == 0F) { continue; } else if (fieldCLass == double.class && propertyValue instanceof Double && ((Double) propertyValue).doubleValue() == 0D) { continue; } else if (fieldCLass == boolean.class && propertyValue instanceof Boolean && !((Boolean) propertyValue).booleanValue()) { continue; } } if (commaFlag) { out.append(','); if (out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.println(); } } if (key != fieldSerializer.getName()) { if (!writeAsArray) { out.writeFieldName(key); } serializer.write(propertyValue); } else if (originalValue != propertyValue) { if (!writeAsArray) { fieldSerializer.writePrefix(serializer); } serializer.write(propertyValue); } else { if (!writeAsArray) { fieldSerializer.writeProperty(serializer,propertyValue); } else { fieldSerializer.writeValue(serializer,propertyValue); } } commaFlag = true; } FilterUtils.writeAfter(serializer,commaFlag ? ',' : '\0'); if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.decrementIdent(); serializer.println(); } out.append(endSeperator); } catch (Exception e) { throw new JSONException("write javaBean error",e); } finally { serializer.setContext(parent); } } }
public class MetaTypeUtils extends TypeUtils { public static List<FieldInfo> computeGetters(Class<?> clazz,String> aliasMap,boolean sorted) { Map<String,FieldInfo> fieldInfoMap = new LinkedHashMap<String,FieldInfo>(); for (Method method : clazz.getMethods()) { String methodName = method.getName(); int ordinal = 0,serialzeFeatures = 0; String label = null; 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; } ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); 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,ordinal,serialzeFeatures,annotation.label())); continue; } if (annotation.label().length() != 0) { label = annotation.label(); } } 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 = decapitalize(methodName.substring(3)); } else { 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 if (methodName.length()>=5 && Character.isUpperCase(methodName.charAt(4))){ propertyName = decapitalize(methodName.substring(3)); } else { continue; } boolean ignore = isJSONTypeIgnore(clazz,propertyName); if (ignore) { continue; } Field field = ParserConfig.getField(clazz,propertyName); if (field != null) { JSONField fieldAnnotation = field.getAnnotation(JSONField.class); if (fieldAnnotation != null) { if (!fieldAnnotation.serialize()) { continue; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } fieldInfoMap.put(propertyName,field,label)); } if (methodName.startsWith("is")) { if (methodName.length() < 3) { continue; } char c2 = methodName.charAt(2); String propertyName; if (Character.isUpperCase(c2)) { if (compatibleWithJavaBean) { propertyName = 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; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } fieldInfoMap.put(propertyName,label)); } } //此处改动:获取所有属性 for (Field field : clazz.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers())) { continue; } JSONField fieldAnnotation = field.getAnnotation(JSONField.class); int ordinal = 0,serialzeFeatures = 0; String propertyName = field.getName(); String label = null; if (fieldAnnotation != null) { if (!fieldAnnotation.serialize()) { continue; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } if (!fieldInfoMap.containsKey(propertyName)) { fieldInfoMap.put(propertyName,label)); } } 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; } private static boolean isJSONTypeIgnore(Class<?> clazz,String propertyName) { JSONType jsonType = clazz.getAnnotation(JSONType.class); if (jsonType != null) { // 1、新增 includes 支持,如果 JSONType 同时设置了includes 和 ignores 属性,则以includes为准。 // 2、个人认为对于大小写敏感的Java和JS而言,使用 equals() 比 equalsIgnoreCase() 更好,改动的唯一风险就是向后兼容性的问题 // 不过,相信开发者应该都是严格按照大小写敏感的方式进行属性设置的 String[] fields = jsonType.includes(); if (fields.length > 0) { for (int i = 0; i < fields.length; i++) { if (propertyName.equals(fields[i])) { return false; } } return true; } else { fields = jsonType.ignores(); for (int i = 0; i < fields.length; i++) { if (propertyName.equals(fields[i])) { return true; } } } } if (clazz.getSuperclass() != Object.class && clazz.getSuperclass() != null) { if (isJSONTypeIgnore(clazz.getSuperclass(),propertyName)) { return true; } } return false; } }
代码使用到了spring的反射工具类,所以依赖spring-core.
注意:理论上不存在问题,但未经过严格测试。