关于struts2 json插件的正则表达式写法的一点儿总结

17 篇文章 0 订阅

最近碰到一个问题,需要将一个集体序列化成json对象,如:List<Person> list=new ArrayList<Person>();

Person对象中有一个属性是Dept类型的,序列化的时候不想将此属性也序列化,也就是要排除该属性,可以在Result中加一个属性,excludeProperties,关键在于值写什么,这是个正则表达式,我还加了一个root参数,值是"list",也就是说让struts2从这个对象开始进行序列化的操作,如果不配的话会默认使用action.

在序列化的过程中,struts2会逐渐进入这个方法

  public String write(Object object, Collection<Pattern> excludeProperties,
                        Collection<Pattern> includeProperties, boolean excludeNullProperties) throws JSONException {
        this.excludeNullProperties = excludeNullProperties;
        this.buf.setLength(0);
        this.root = object;
        this.exprStack = "";
        this.buildExpr = ((excludeProperties != null) && !excludeProperties.isEmpty())
                || ((includeProperties != null) && !includeProperties.isEmpty());
        this.excludeProperties = excludeProperties;
        this.includeProperties = includeProperties;
        this.value(object, null);

        return this.buf.toString();
    }

其中的root就是我配的list对象了.最重要的一步是调用value方法,咱们看看这个方法,

   this.process(object, method);


这个方法中又调用了process方法来处理这个对象,

private void process(Object object, Method method) throws JSONException {
        this.stack.push(object);

        if (object instanceof Class) {
            this.string(object);
        } else if (object instanceof Boolean) {
            this.bool((Boolean) object);
        } else if (object instanceof Number) {
            this.add(object);
        } else if (object instanceof String) {
            this.string(object);
        } else if (object instanceof Character) {
            this.string(object);
        } else if (object instanceof Map) {
            this.map((Map) object, method);
        } else if (object.getClass().isArray()) {
            this.array(object, method);
        } else if (object instanceof Iterable) {
            this.array(((Iterable) object).iterator(), method);
        } else if (object instanceof Date) {
            this.date((Date) object, method);
        } else if (object instanceof Calendar) {
            this.date(((Calendar) object).getTime(), method);
        } else if (object instanceof Locale) {
            this.string(object);
        } else if (object instanceof Enum) {
            this.enumeration((Enum) object);
        } else {
            this.bean(object);
        }

        this.stack.pop();
    }

这个里面其实就是根据对象的类型来调用相应的方法来处理,可以看出struts2 json插件支持的数据类型.由于咱们是list类型的,会调用 array这个方法.

 private void array(Iterator it, Method method) throws JSONException {
        this.add("[");

        boolean hasData = false;
        for (int i = 0; it.hasNext(); i++) {
            String expr = null;
            if (this.buildExpr) {
                expr = this.expandExpr(i);
                if (this.shouldExcludeProperty(expr)) {
                    it.next();
                    continue;
                }
                expr = this.setExprStack(expr);
            }
            if (hasData) {
                this.add(',');
            }
            hasData = true;
            this.value(it.next(), method);
            if (this.buildExpr) {
                this.setExprStack(expr);
            }
        }

        this.add("]");
    }


add方法就是在最后的结果添加字符串,expandExpr方法就是用来产生正则是表达式的,对每一个属性,都会产生一个正则是表达式,可以看出表达式里面现在是[0],

然后又调用value方法处理第一个person对象.

person对象是Object类型的,在process方法中会调用bean方法,

   PropertyDescriptor[] props = info.getPropertyDescriptors();

            boolean hasData = false;
            for (PropertyDescriptor prop : props) {
                String name = prop.getName();
                Method accessor = prop.getReadMethod();
                Method baseAccessor = findBaseAccessor(clazz, accessor);

                if (baseAccessor != null) {
                    if (baseAccessor.isAnnotationPresent(JSON.class)) {
                        JSONAnnotationFinder jsonFinder = new JSONAnnotationFinder(baseAccessor).invoke();

                        if (!jsonFinder.shouldSerialize()) continue;
                        if (jsonFinder.getName() != null) {
                            name = jsonFinder.getName();
                        }
                    }
                    // ignore "class" and others
                    if (this.shouldExcludeProperty(prop)) {
                        continue;
                    }
                    String expr = null;
                    if (this.buildExpr) {
                        expr = this.expandExpr(name);
                        if (this.shouldExcludeProperty(expr)) {
                            continue;
                        }
                        expr = this.setExprStack(expr);
                    }

                    Object value = accessor.invoke(object);
                    if (baseAccessor.isAnnotationPresent(JSONFieldBridge.class)) {
                        value = getBridgedValue(baseAccessor, value);
                    }

                    boolean propertyPrinted = this.add(name, value, accessor, hasData);
                    hasData = hasData || propertyPrinted;
                    if (this.buildExpr) {
                        this.setExprStack(expr);
                    }
                }
            }


在bean方法中会得到这个对象的所有属性,然后遍历属性,如果属性名称为id,则通过expandExpr方法会生成[0].id这个表达式,然后在shouldExcludeProperty方法中跟你传的正则表达式进行比较,如果匹配上就会忽略掉该属性,这个方法里面有两个比较,一个是忽略(excludeProperties)的比较,一个是包含(includeProperties)的比较,会先进行忽略的比较,因此,如果匹配上了,就直接返回true,就不会进行包含的比较,这就跟短路的情况差不多,如果没有匹配,则进行下一个属性的比较.

我们更关心的是这个表达式的规则是怎样的,因此其他细节性的东西我们不必要去关注.

有不清楚的情况的话可以再跟踪源代码看.


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值