spring boot項目實戰(zhàn)之工具篇(ognl)

當(dāng)解析復(fù)雜的json結(jié)構(gòu)時幻梯,ognl是一個很方便的工具,實現(xiàn)基于圖對屬性的訪問瓦宜,類似于以(user.name | user.depart[0])的方式獲取json內(nèi)的嵌套對象字段值。

請看以下示例,你將對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]"));
  • 內(nèi)部對象的普通字段可以通過user.name這樣的方式獲取
  • 內(nèi)部對象的集合字段可以通過user.depart.size獲取其集合長度
  • 內(nèi)部對象的集合字段可以通過user.depart[0]的方式獲取對應(yīng)下標(biāo)出的值

通常json對象解析可以通過一層一層的轉(zhuǎn)換為map來實現(xiàn)凭戴,但如果嵌套對象層次有3層以上,內(nèi)部結(jié)構(gòu)較復(fù)雜炕矮,那實現(xiàn)起來就很繁瑣么夫,代碼冗長者冤,這種情況下使用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類的一個工具類钞它,實現(xiàn)基于圖對屬性的訪問拜银,支持ognl的所有語法。 提供三個核心方法:
get();
getLong(); //如果值非long型遭垛,將返回null
getInt(); //如果值非int型尼桶,將返回null

使用注意

在使用Long longvalue = ognlWrapper.get("body.payload.page.page_size"); 時出現(xiàn)如下錯誤: 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(); //設(shè)置用戶的相關(guān)屬性
//...省略屬性設(shè)置
//使用OgnlWrapper
OgnlWrapper ognlWrapper = new OgnlWrapper(user);
String id = ognlWrapper.get("id");//獲取id

//狀態(tài). 請使用基本數(shù)據(jù)類型的封裝類型
Integer status = ognlWrapper.getInt("status");  
//聯(lián)系信息中的郵件地址
String email = ognlWrapper.get("contact_info.email");

//獲取一個不存在的屬性
//將返回null
String noexist = ognlWrapper.get("noexist");
 
//將返回null
noexist = ognlWrapper.get("contact_info.noexist");

對list操作

//將存放用戶的列表數(shù)據(jù)放到map中 map.put("users",list);
//使用OgnlWrapper獲取用戶列表數(shù)據(jù)
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 注意:下標(biāo)從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內(nèi)rest-base項目com.onecoderspace.base.util.ognl.OgnlWrapper久窟。
https://github.com/q7322068/rest-base

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秩冈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子斥扛,更是在濱河造成了極大的恐慌入问,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稀颁,死亡現(xiàn)場離奇詭異芬失,居然都是意外死亡,警方通過查閱死者的電腦和手機匾灶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門棱烂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阶女,你說我怎么就攤上這事颊糜。” “怎么了秃踩?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵芭析,是天一觀的道長。 經(jīng)常有香客問我吞瞪,道長馁启,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮惯疙,結(jié)果婚禮上翠勉,老公的妹妹穿的比我還像新娘。我一直安慰自己霉颠,他們只是感情好对碌,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒿偎,像睡著了一般朽们。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诉位,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天骑脱,我揣著相機與錄音,去河邊找鬼苍糠。 笑死叁丧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岳瞭。 我是一名探鬼主播拥娄,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瞳筏!你這毒婦竟也來了稚瘾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤姚炕,失蹤者是張志新(化名)和其女友劉穎孟抗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钻心,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年铅协,在試婚紗的時候發(fā)現(xiàn)自己被綠了捷沸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狐史,死狀恐怖痒给,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骏全,我是刑警寧澤苍柏,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站姜贡,受9級特大地震影響试吁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一熄捍、第九天 我趴在偏房一處隱蔽的房頂上張望烛恤。 院中可真熱鬧,春花似錦余耽、人聲如沸缚柏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽币喧。三九已至,卻和暖如春袱耽,著一層夾襖步出監(jiān)牢的瞬間杀餐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工扛邑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怜浅,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓蔬崩,卻偏偏與公主長得像恶座,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沥阳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理跨琳,服務(wù)發(fā)現(xiàn),斷路器桐罕,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法脉让,類相關(guān)的語法,內(nèi)部類的語法功炮,繼承相關(guān)的語法溅潜,異常的語法,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,965評論 6 13
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,810評論 0 11
  • 其實有好多話薪伏。卻又不知從何說起滚澜。工作怎么樣。該不該繼續(xù)嫁怀。生活怎么樣设捐。該不該改變。習(xí)慣怎么樣塘淑。 我知道我現(xiàn)在一點都不...
    樂樂樂樂樂樂閱讀 159評論 0 1