美文网首页spring boot项目实战程序员Spring Boot
spring boot项目实战之工具篇(ognl)

spring boot项目实战之工具篇(ognl)

作者: 思与学 | 来源:发表于2017-10-07 20:57 被阅读124次

    当解析复杂的json结构时,ognl是一个很方便的工具,实现基于图对属性的访问,类似于以(user.name | user.depart[0])的方式获取json内的嵌套对象字段值。

    请看以下示例,你将对ognl的作用有一个更清晰的理解:

    String json = "{\"user\":{\"name\":\"123\",\"depart\":[1,2]}}";
    Map<?, ?> map = JacksonHelper.fromJson(json, Map.class);
    OgnlWrapper ognlWrapper = new OgnlWrapper(map);
    System.err.println(ognlWrapper.get("user.name"));
    System.err.println(ognlWrapper.get("user.depart.size"));
    System.err.println(ognlWrapper.get("user.depart[0]"));
    
    • 内部对象的普通字段可以通过user.name这样的方式获取
    • 内部对象的集合字段可以通过user.depart.size获取其集合长度
    • 内部对象的集合字段可以通过user.depart[0]的方式获取对应下标出的值

    通常json对象解析可以通过一层一层的转换为map来实现,但如果嵌套对象层次有3层以上,内部结构较复杂,那实现起来就很繁琐,代码冗长,这种情况下使用ognl能让代码精简很多。

    1、添加maven依赖

    <!-- ognl -->
    <dependency>
        <groupId>ognl</groupId>
        <artifactId>ognl</artifactId>
        <version>3.2.1</version>
    </dependency>
    

    2、OgnlWrapper

    @SuppressWarnings("unchecked")
    public class OgnlWrapper {
    
        private static Logger logger = LoggerFactory.getLogger(OgnlWrapper.class);
    
        private static ObjectMapper om = new ObjectMapper();
        private Map<String, Object> payload;
    
        public OgnlWrapper(Map<String, Object> playload) {
            Validate.notEmpty(playload, "can not construct with none playload!");
            this.payload = playload;
        }
    
        
        public OgnlWrapper(Object playload) {
            this.payload = om.convertValue(playload, Map.class);
        }
    
        public <T> T get(String expression) {
            try {
                return (T) Ognl.getValue(expression, this.payload);
            } catch (OgnlException e) {
                logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                    expression), e);
                return null;
            }
        }
    
        public Long getLong(String expression) {
            try {
                Object obj = Ognl.getValue(expression, this.payload);
                if (null == obj)
                    return null;
                try {
                    return Long.parseLong(obj.toString());
                } catch (NumberFormatException nfe) {
                    logger.warn(String.format("get value with expression:[%s] due to error, return null. value[%s] cannot be cast to java.lang.Long",
                        expression,
                        obj.toString()));
                    return null;
                }
            } catch (OgnlException e) {
                logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                    expression), e);
                return null;
            }
        }
    
        public Integer getInt(String expression) {
            try {
                Object obj = Ognl.getValue(expression, this.payload);
                if (null == obj)
                    return null;
                try {
                    return Integer.parseInt(obj.toString());
                } catch (NumberFormatException nfe) {
                    logger.warn(String.format("get value with expression:[%s] due to error, return null. value[%s] cannot be cast to java.lang.Integer",
                        expression,
                        obj.toString()));
                    return null;
                }
            } catch (OgnlException e) {
                logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                    expression), e);
                return null;
            }
        }
    
        @Override
        public String toString() {
            return String.format("OgnlWrapper[%s]", this.payload.toString());
        }
        
        public static void main(String[] args) {
            String json = "{\"user\":{\"name\":\"123\",\"depart\":[1,2]}}";
            Map<?, ?> map = JacksonHelper.fromJson(json, Map.class);
            OgnlWrapper ognlWrapper = new OgnlWrapper(map);
            System.err.println(ognlWrapper.get("user.name"));
            System.err.println(ognlWrapper.get("user.depart.size"));
            System.err.println(ognlWrapper.get("user.depart[0]"));
        }
    }
    

    3、使用手册

    说明

    OgnlWrapper是基于ognl.Ognl类的一个工具类,实现基于图对属性的访问,支持ognl的所有语法。 提供三个核心方法:
    get();
    getLong(); //如果值非long型,将返回null
    getInt(); //如果值非int型,将返回null

    使用注意

    在使用Long longvalue = ognlWrapper.get("body.payload.page.page_size"); 时出现如下错误: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
    解决方法:使用getLong方法
    Long longvalue = ognlWrapper.getLong("body.payload.page.page_size");

    获取不存在的属性时返回null,日志中会打印warn警告日志。 如:ognlWrapper.getLong("body.payload[0].childrens[0].childrens.size"); // return null

    单个对象

    User user = new User(); //设置用户的相关属性
    //...省略属性设置
    //使用OgnlWrapper
    OgnlWrapper ognlWrapper = new OgnlWrapper(user);
    String id = ognlWrapper.get("id");//获取id
    
    //状态. 请使用基本数据类型的封装类型
    Integer status = ognlWrapper.getInt("status");  
    //联系信息中的邮件地址
    String email = ognlWrapper.get("contact_info.email");
    
    //获取一个不存在的属性
    //将返回null
    String noexist = ognlWrapper.get("noexist");
     
    //将返回null
    noexist = ognlWrapper.get("contact_info.noexist");
    

    对list操作

    //将存放用户的列表数据放到map中 map.put("users",list);
    //使用OgnlWrapper获取用户列表数据
    OgnlWrapper ognlWrapper = new OgnlWrapper(map);
    
    //获取list大小。如果map未存放list则返回null
    Integer size = ognlWrapper.getInt("users.size"); 
    if(null == size || 0 == size.intValue())  return ;
    
    //获取list中第一用户的用户id和name 注意:下标从0开始
    String id = ognlWrapper.get("users[0].id");
    String name = ognlWrapper.get("users[0].name");
    
    //如果索引超出list的大小,将返回null
    String nullvalue = ognlWrapper.get("users[9999999].id");    
    

    使用OgnlWrapper获取属性值时,请使用对象类型。如int 使用Integer类型。

    完整代码请参考github内rest-base项目com.onecoderspace.base.util.ognl.OgnlWrapper。
    https://github.com/q7322068/rest-base

    相关文章

      网友评论

        本文标题:spring boot项目实战之工具篇(ognl)

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