Python-jmespath學(xué)習(xí)

基礎(chǔ)表達(dá)式

基礎(chǔ)表達(dá)語法寸宵,類似JavaScript的取列表值恤煞、對(duì)象值,互相組合取嵌套值刊苍。

import jmespath

print(jmespath.search('a', {"a": "foo", "b": "bar", "c": "baz"}))  
print(jmespath.search('a.b.c.d', {"a": {"b": {"c": {"d": "value"}}}}))
print(jmespath.search('[1]', ["a", "b", "c", "d", "e", "f"]))
print(jmespath.search('a.b.c[0].d[1][0]', {"a": {"b": {"c": [{"d": [0, [1, 2]]}, {"d": [3, 4]}]}}}))
# 輸出
foo
value
b
1

切片

和Python的列表切片語法完全一致。

import jmespath

print(jmespath.search('[0:5]', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(jmespath.search('[5:10]', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(jmespath.search('[:5]', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(jmespath.search('[::2]', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(jmespath.search('[::-1]', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
# output
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

列表和切片投影

[*]第一個(gè)只包含三個(gè)元素濒析,盡管people數(shù)組有四個(gè)元素正什。這是因?yàn)楫?dāng)表達(dá)式第一次應(yīng)用時(shí),最后一個(gè)元素{"missing": "different"}的值為空号杏,空值不會(huì)被添加到收集的結(jié)果數(shù)組中婴氮。如果您嘗試表達(dá)式foo[*].bar,你會(huì)看到一個(gè)null的結(jié)果盾致,因?yàn)榕cfoo鍵相關(guān)聯(lián)的值是一個(gè)JSON對(duì)象主经,而不是一個(gè)數(shù)組,并且列表投影僅為JSON數(shù)組定義庭惜。

切片投影和列表投影幾乎是一樣的罩驻,唯一不同的是,左邊的投影是計(jì)算切片的結(jié)果护赊,它可能不包括原始列表中的所有元素鉴腻。

import jmespath

data = {
    "people": [
        {"first": "James", "last": "d"},
        {"first": "Jacob", "last": "e"},
        {"first": "Jayden", "last": "f"},
        {"missing": "different"}
    ],
    "foo": {"bar": "baz"}
}
print(jmespath.search('people[*].first', data))  # 列表投影
print(jmespath.search('people[0:3].first', data))   # 切片投影
# output
['James', 'Jacob', 'Jayden']
['James', 'Jacob', 'Jayden']

對(duì)象投影

列表投影是為JSON數(shù)組定義的,而對(duì)象投影是為JSON對(duì)象定義的百揭。可以使用*語法創(chuàng)建對(duì)象投影蜓席。這將創(chuàng)建JSON對(duì)象的值列表器一,并將投影的右側(cè)投影到值列表上。

import jmespath

data = {
    "ops": {
        "functionA": {"numArgs": 2},
        "functionB": {"numArgs": 3},
        "functionC": {"variadic": True},
        "functionD": 3
    }
}
print(jmespath.search('ops.*', data))   # 創(chuàng)建JSON對(duì)象的值列表
print(jmespath.search('ops.*.numArgs', data))
# output
[{'numArgs': 2}, {'numArgs': 3}, {'variadic': True}, 3]
[2, 3]

Flatten Projections(扁平投影)

下面是列表投影和對(duì)象投影組合使用厨内,結(jié)果嵌套了很多層列表祈秕,可讀性差。
我們希望得到一個(gè)結(jié)果["running"雏胃, "stopped"请毛, "terminated", "running"]瞭亮。在這種情況下方仿,我們不關(guān)心實(shí)例屬于哪個(gè)保留,我們只需要一個(gè)列表统翩。
這就是Flatten投影解決的問題仙蚜。要得到想要的結(jié)果,可以使用[]而不是[*]來平鋪列表:嘗試將上面表達(dá)式中的[*]更改為[]

import jmespath

data = {
    "reservations": [
        {
            "instances": [
                {"state": "running"},
                {"state": "stopped"}
            ]
        },
        {
            "instances": [
                {"state": "terminated"},
                {"state": "running"}
            ]
        }
    ]
}
print(jmespath.search('reservations[*].instances[*]', data))
print(jmespath.search('reservations[*].instances[*].*', data))
print(jmespath.search('reservations[*].instances[*].state', data))
# output
[[{'state': 'running'}, {'state': 'stopped'}], [{'state': 'terminated'}, {'state': 'running'}]]
[[['running'], ['stopped']], [['terminated'], ['running']]]
[['running', 'stopped'], ['terminated', 'running']]

結(jié)果就很符合期望了厂汗,看起來很順眼委粉。

import jmespath

data = {
    "reservations": [
        {
            "instances": [
                {"state": "running"},
                {"state": "stopped"}
            ]
        },
        {
            "instances": [
                {"state": "terminated"},
                {"state": "running"}
            ]
        }
    ]
}
print(jmespath.search('reservations[].instances[].state', data))
# output
['running', 'stopped', 'terminated', 'running']

當(dāng)然,也可以直接使用[]or[][]進(jìn)行列表扁平投影娶桦。

import jmespath

data = [
    [0, 1],
    2,
    [3],
    4,
    [5, [6, 7]]
]
print(jmespath.search('[*]', data))
print(jmespath.search('[]', data))
print(jmespath.search('[][]', data))
# output
[[0, 1], 2, [3], 4, [5, [6, 7]]]
[0, 1, 2, 3, 4, 5, [6, 7]]
[0, 1, 2, 3, 4, 5, 6, 7]

過濾投影

如同其名稱贾节,過濾投影的作用就是去除不滿足過濾條件的數(shù)據(jù)汁汗,語法:LHS [? <expression> <comparator> <expression>] RHS,comparators支持這些 ==, !=, <, <=, >, >=栗涂。

下面的例子就是獲取狀態(tài)為running的機(jī)器名稱知牌。

import jmespath

data = {
    "machines": [
        {"name": "a", "state": "running"},
        {"name": "b", "state": "stopped"},
        {"name": "c", "state": "running"}
    ]
}
print(jmespath.search("machines[?state=='running'].name", data))
# output
['a', 'c']

上面那個(gè)例子的過濾條件是字符串status=="running",但有時(shí)候會(huì)遇到過濾條件是number整數(shù)類型戴差。
下面這個(gè)例子想獲取exchange_type==13的數(shù)據(jù)送爸,剛開始是這么寫的[?exchange_type==13],也試了[?exchange_type=='13']暖释,結(jié)果是報(bào)錯(cuò)或者是數(shù)據(jù)為空袭厂。正確的寫法是"data.exchange_config_list[?exchange_type==`13`]",注意不是單引號(hào)也不是雙引號(hào)球匕,是反單引號(hào)纹磺。

import jmespath

data = {"code": 200, "data": {"base_rsp": {"ret": 0, "rsp_msg": "", "seq": 0}, "exchange_config_list": [
    {"already_exchange_num": 1, "exchange_id": 30217, "exchange_type": 13, "expired_day": 0, "fragments_num": 1,
     "fragments_type": 1, "most_exchange_num": 1, "weight": 10000},
    {"already_exchange_num": 485, "exchange_id": 90124, "exchange_type": 1, "expired_day": 10, "fragments_num": 3,
     "fragments_type": 2, "most_exchange_num": 99999, "weight": 999},
    {"already_exchange_num": 0, "exchange_id": 30174, "exchange_type": 13, "expired_day": 0, "fragments_num": 6570,
     "fragments_type": 1, "most_exchange_num": 2, "weight": 1}]}, "elapsed_time": 7, "message": "請(qǐng)求成功", "ret": 0}

print(jmespath.search("data.exchange_config_list[?exchange_type==`13`].exchange_id", data))
# output
[30217, 30174]

多條件過濾投影,有||,&&,>,<等等亮曹。

import jmespath

data = {"code": 200, "data": {"base_rsp": {"ret": 0, "rsp_msg": "", "seq": 0}, "exchange_config_list": [
    {"already_exchange_num": 1, "exchange_id": 30217, "exchange_type": 13, "expired_day": 0, "fragments_num": 1,
     "fragments_type": 1, "most_exchange_num": 1, "weight": 10000},
    {"already_exchange_num": 485, "exchange_id": 90124, "exchange_type": 1, "expired_day": 10, "fragments_num": 3,
     "fragments_type": 2, "most_exchange_num": 99999, "weight": 999},
    {"already_exchange_num": 0, "exchange_id": 30174, "exchange_type": 13, "expired_day": 0, "fragments_num": 6570,
     "fragments_type": 1, "most_exchange_num": 2, "weight": 1}]}, "elapsed_time": 7, "message": "請(qǐng)求成功", "ret": 0}

print(jmespath.search("data.exchange_config_list[?exchange_type==`13`].exchange_id", data))
print(jmespath.search("data.exchange_config_list[?exchange_type==`13` || exchange_type==`1`].exchange_id", data))
print(jmespath.search("data.exchange_config_list[?exchange_type==`13` && weight==`1`].exchange_id", data))
# output
[30217, 30174]
[30217, 90124, 30174]
[30174]

管道符|語法

投影是JMESPath中的一個(gè)重要概念橄杨。然而,有些時(shí)候投影語義并不是您想要的照卦。一種常見的情況是式矫,您希望操作投影的結(jié)果,而不是將表達(dá)式投影到數(shù)組中的每個(gè)元素上役耕。例如采转,表達(dá)式people[*]。First將為您提供一個(gè)包含people數(shù)組中每個(gè)人的名字的數(shù)組瞬痘。如果你想要列表中的第一個(gè)元素呢?如果你試過別人[*]故慈。第一個(gè)[0],您只是為people數(shù)組中的每個(gè)元素計(jì)算第一個(gè)[0]框全,并且由于沒有為字符串定義索引察绷,最終結(jié)果將是一個(gè)空數(shù)組。要實(shí)現(xiàn)預(yù)期的結(jié)果津辩,可以使用管道表達(dá)式<表達(dá)式> | <表達(dá)式>來指示必須停止投影拆撼。
如下面的例子所示,后面新增一個(gè)表達(dá)式對(duì)數(shù)據(jù)進(jìn)行處理喘沿,可以是過濾條件情萤,有可能是索引表達(dá)式,得到期望的數(shù)據(jù)摹恨。

import jmespath

data = {
    "people": [
        {"first": "James", "last": "d"},
        {"first": "Jacob", "last": "e"},
        {"first": "Jayden", "last": "f"},
        {"missing": "different"}
    ],
    "foo": {"bar": "baz"}
}
print(jmespath.search("people[*]", data))
print(jmespath.search("people[*] | [?last=='e']", data))

print(jmespath.search("people[*].first", data))
print(jmespath.search("people[*].first | [0]", data))
# output
[{'first': 'James', 'last': 'd'}, {'first': 'Jacob', 'last': 'e'}, {'first': 'Jayden', 'last': 'f'}, {'missing': 'different'}]
[{'first': 'Jacob', 'last': 'e'}]
['James', 'Jacob', 'Jayden']
James

MultiSelect多選

多選列表和多選散列允許您創(chuàng)建JSON元素筋岛。這允許您創(chuàng)建JSON對(duì)象中不存在的元素。多選列表創(chuàng)建一個(gè)列表晒哄,多選散列創(chuàng)建一個(gè)JSON對(duì)象睁宰。
說人話肪获,多選散列就是多選哈希,也就是多選字典柒傻。
列表多選
如下面的例子孝赫,列表多選創(chuàng)建JSON對(duì)象中不存在的元素。

import jmespath

data = {
    "people": [
        {
            "name": "a",
            "state": {"name": "up"}
        },
        {
            "name": "b",
            "state": {"name": "down"}
        },
        {
            "name": "c",
            "state": {"name": "up"}
        }
    ]
}
print(jmespath.search("people[].name", data))
print(jmespath.search("people[].[name, state.name]", data))
# output
['a', 'b', 'c']
[['a', 'up'], ['b', 'down'], ['c', 'up']]

對(duì)象多選红符,又稱哈希多選青柄,又稱散列多選。
如下面的例子预侯,key值是自己定義致开,value值是表達(dá)式計(jì)算出來的。

import jmespath

data = {
    "people": [
        {
            "name": "a",
            "state": {"name": "up"}
        },
        {
            "name": "b",
            "state": {"name": "down"}
        },
        {
            "name": "c",
            "state": {"name": "up"}
        }
    ]
}
print(jmespath.search("people[].{Name: name, State: state.name}", data))
# output
[{'Name': 'a', 'State': 'up'}, {'Name': 'b', 'State': 'down'}, {'Name': 'c', 'State': 'up'}]

Functions函數(shù)

jmespath有內(nèi)置函數(shù)處理數(shù)據(jù)萎馅,文檔如下內(nèi)置函數(shù)
length()双戳,獲取列表長度,適用于列表對(duì)象糜芳。

import jmespath

data = {
    "people": [
        {
            "name": "b",
            "age": 30
        },
        {
            "name": "a",
            "age": 50
        },
        {
            "name": "c",
            "age": 40
        }
    ]
}
print(jmespath.search("length(people)", data))
# output
3

max_by()飒货,以某個(gè)值為維度丹允,取最大值蝠咆。
如下面例子及舍,取people列表age最大的列表元素

import jmespath

data = {
    "people": [
        {
            "name": "b",
            "age": 30
        },
        {
            "name": "a",
            "age": 50
        },
        {
            "name": "c",
            "age": 40
        }
    ]
}
print(jmespath.search('max_by(people, &age)', data))
# output
{'name': 'a', 'age': 50}

contains()寒跳,是否包含某個(gè)元素
下面的例子是獲取myarray列表中包含foo的元素。

import jmespath

data = {
    "myarray": [
        "foo",
        "foobar",
        "barfoo",
        "bar",
        "baz",
        "barbaz",
        "barfoobaz"
    ]
}
print(jmespath.search("myarray[?contains(@, 'foo') == `true`]", data))
# output
['foo', 'foobar', 'barfoo', 'barfoobaz']

@指向數(shù)據(jù)問題
如下面兩個(gè)例子得出屠橄,@指向當(dāng)前操作的列表對(duì)象刃唤,也有可能是字典對(duì)象结啼。

import jmespath

data1 = {
    "myarray": [
        "foo",
        "foobar",
        "barfoo",
        "bar",
        "baz",
        "barbaz",
        "barfoobaz"
    ]
}
data2 = [
    "foo",
    "foobar",
    "barfoo",
    "bar",
    "baz",
    "barbaz",
    "barfoobaz"
]
print(jmespath.search("myarray[?contains(@, 'foo') == `true`]", data1))    # @指向myarray列表
print(jmespath.search("[?contains(@, 'foo') == `true`]", data2))  # @指向data2列表
# output
['foo', 'foobar', 'barfoo', 'barfoobaz']
['foo', 'foobar', 'barfoo', 'barfoobaz']
import jmespath

data1 = {
    "people": [
        {
            "name": "b",
            "age": 30
        },
        {
            "name": "a",
            "age": 50
        },
        {
            "name": "c",
            "age": 40
        }
    ]
}
data2 = [
    {
        "name": "b",
        "age": 30
    },
    {
        "name": "a",
        "age": 50
    },
    {
        "name": "c",
        "age": 40
    }
]

print(jmespath.search('max_by(people, &age)', data1))
print(jmespath.search('max_by(@, &age)', data2))
# output
{'name': 'a', 'age': 50}
{'name': 'a', 'age': 50}

數(shù)字作為key值毅访,keys和values方法取字典的鍵值

key值是number數(shù)據(jù)類型,取值如下:

import jmespath
my_list = {
    "code": 200,
    "data": {
        "base_rsp": {
            "ret": 0,
            "rsp_msg": "",
            "seq": 0
        },
        "uid_follow_status_map": {
            "17230530": 1
        }
    },
    "elapsed_time": 9,
    "message": "\u8bf7\u6c42\u6210\u529f",
    "ret": 0
}

print(jmespath.search('data.uid_follow_status_map."17230530"', my_list))  #數(shù)字作為鍵值盘榨,需要用雙引號(hào)喻粹,且單引號(hào)在外邊
print(jmespath.search('values(data.uid_follow_status_map)|[0]', my_list))  #取字典的key或者value值,使用values方法和keys方法

##輸出
1
1

httprunner框架extract提取語法問題

httprunner項(xiàng)目使用jmespath提取字段草巡,但是不完全支持守呜,存在以下問題
表達(dá)式不支持傳遞參數(shù)
表達(dá)式不能格式化傳參:body.data.bbs_id_list[?exchange_type={}].formmat(type)

列表切片索引不支持負(fù)數(shù)
body.data.bbs_id_list[-1],這個(gè)在httprunner執(zhí)行提取不了數(shù)據(jù)山憨,在Python執(zhí)行環(huán)境時(shí)正常的查乒。
可以用reverse方法進(jìn)行列表反轉(zhuǎn)

print(jmespath.search('data.bbs_id_list[]', data))
print(jmespath.search('reverse(data.bbs_id_list[])', data))
print(jmespath.search('reverse(data.bbs_id_list[])|[0]', data))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郁竟,隨后出現(xiàn)的幾起案子玛迄,更是在濱河造成了極大的恐慌,老刑警劉巖棚亩,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓖议,死亡現(xiàn)場離奇詭異虏杰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)勒虾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門纺阔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人修然,你說我怎么就攤上這事笛钝。” “怎么了愕宋?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵玻靡,是天一觀的道長。 經(jīng)常有香客問我掏婶,道長啃奴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任雄妥,我火速辦了婚禮最蕾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘老厌。我一直安慰自己瘟则,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布枝秤。 她就那樣靜靜地躺著醋拧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪淀弹。 梳的紋絲不亂的頭發(fā)上丹壕,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音薇溃,去河邊找鬼菌赖。 笑死,一個(gè)胖子當(dāng)著我的面吹牛沐序,可吹牛的內(nèi)容都是我干的琉用。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼策幼,長吁一口氣:“原來是場噩夢啊……” “哼邑时!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起特姐,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤晶丘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后唐含,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铣口,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滤钱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脑题。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片件缸。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖叔遂,靈堂內(nèi)的尸體忽然破棺而出他炊,到底是詐尸還是另有隱情,我是刑警寧澤已艰,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布痊末,位于F島的核電站,受9級(jí)特大地震影響哩掺,放射性物質(zhì)發(fā)生泄漏凿叠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一嚼吞、第九天 我趴在偏房一處隱蔽的房頂上張望盒件。 院中可真熱鬧,春花似錦舱禽、人聲如沸炒刁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翔始。三九已至,卻和暖如春里伯,著一層夾襖步出監(jiān)牢的瞬間城瞎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工疾瓮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脖镀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓爷贫,卻偏偏與公主長得像认然,于是被迫代替她去往敵國和親补憾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漫萄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • 寫在前面的話 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,758評(píng)論 0 8
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常盈匾。 O...
    我想起個(gè)好名字閱讀 5,317評(píng)論 0 9
  • 為什么用elasticsearch 在引入elasticsearch前腾务,我們的數(shù)據(jù)一般都存儲(chǔ)在mysql上,所有的...
    遞歸宇宙閱讀 1,009評(píng)論 0 0
  • 表情是什么削饵,我認(rèn)為表情就是表現(xiàn)出來的情緒岩瘦。表情可以傳達(dá)很多信息未巫。高興了當(dāng)然就笑了,難過就哭了启昧。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,052評(píng)論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者叙凡,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn)密末,也就放棄了無數(shù)的可能握爷。 ...
    yichen大刀閱讀 6,052評(píng)論 0 4