美文网首页
SPEL解析JSON或MAP

SPEL解析JSON或MAP

作者: TinyThing | 来源:发表于2020-07-07 11:39 被阅读0次

    背景:
    在某项目中,需要使用el表达式对json进行解析;后端先将json序列化为一个map,然后将这个map作为root对象进行el解析,结果报错:

    Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'sub' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public or not valid?
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217)
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:91)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:61)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91)
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:272)
    

    研究后发现,采用el表达式进行解析,针对map的解析写法比较复杂:

    map['student']['address']['city']
    

    以上写法不优雅,为了更优雅的兼容map解析,需要对原有的StandardEvaluationContext添加一个属性访问器:MapAccessor
    这样就可以通过如下写法获取属性:

    map.student.address.city
    

    代码如下:

        /**
         * spel解析器
         */
        private static final SpelExpressionParser parser= new SpelExpressionParser();
    
        /**
         * spel缓存
         */
        private static final ConcurrentHashMap<String, Expression> expressionMap = new ConcurrentHashMap<>(256);
    
    
    
        public static void main(String[] args) {
    //        String el = "#root['student']['address']['city']";
            String el = "student.address.city";
    
            Map<String, Object> address = new HashMap<>();
            address.put("city", "北京");
            Map<String, Object> student = new HashMap<>();
            student.put("address", address);
            Map<String, Object> root = new LinkedHashMap<>();
            root.put("student", student);
    
    
            Expression expression = getExpression(el);
    
            StandardEvaluationContext context = new StandardEvaluationContext(root);
            //这里很关键,如果没有配置MapAccessor,那么只能用['c']['a']这种解析方式
            context.addPropertyAccessor(new MapAccessor());
    
            Object value = expression.getValue(context);
            System.out.println(value);
        }
    
    
        /**
         * 从缓存中获取spel编译表达式
         *
         * @return              SpelExpression
         */
        private static Expression getExpression(String el) {
            Expression expression = expressionMap.get(el);
    
            if (expression != null) {
                return expression;
            }
    
            return expressionMap.computeIfAbsent(el, k -> parser.parseRaw(el));
        }
    
    
    

    相关文章

      网友评论

          本文标题:SPEL解析JSON或MAP

          本文链接:https://www.haomeiwen.com/subject/hzlaqktx.html