Json   发布时间:2022-04-22  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Alibaba FastJson支持对象中私有属性的json解析大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
项目中需要使用fastjson做数据处理,而且部分对象中的属性很多都是第三方的非public的,且没有getter/setter方法,找了很久没有找到fastjson对这个问题的解决
所以自己动手,基于fastjson的源代码构造了单独的javabean的序列化器。
使用方式:直接使用封装好的MetaJsonUtil的工具方法即可。
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.

注意:理论上不存在问题,但未经过严格测试。

大佬总结

以上是大佬教程为你收集整理的Alibaba FastJson支持对象中私有属性的json解析全部内容,希望文章能够帮你解决Alibaba FastJson支持对象中私有属性的json解析所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。