本文深入探討如何利用 `jq` 工具高效地遞歸處理 JSON 數(shù)據(jù),實(shí)現(xiàn)空值(包括空字符串、空數(shù)組、空對象及僅含空白的字符串)的移除、字符串布爾值的類型轉(zhuǎn)換以及所有字符串(包括鍵)的首尾空白字符清理。文章將分析常見實(shí)現(xiàn)方式的性能瓶頸,并提供一個(gè)優(yōu)化的自定義 `walk` 函數(shù),以提升處理復(fù)雜嵌套 JSON 結(jié)構(gòu)時(shí)的 CPU 效率。
在數(shù)據(jù)預(yù)處理過程中,面對復(fù)雜且嵌套的 JSON 數(shù)據(jù),我們經(jīng)常需要執(zhí)行一系列清理和標(biāo)準(zhǔn)化操作。例如,移除各種形式的“空”值、將特定字符串轉(zhuǎn)換為其對應(yīng)的布爾類型,以及統(tǒng)一清理字符串中的多余空白。jq 作為一款強(qiáng)大的命令行 JSON 處理器,是完成此類任務(wù)的理想工具。然而,對于大規(guī)?;蛏疃惹短椎?JSON 數(shù)據(jù),如何編寫高效的 jq 查詢以避免不必要的 CPU 消耗,則成為一個(gè)關(guān)鍵挑戰(zhàn)。
我們的目標(biāo)是遞歸地對 JSON 數(shù)據(jù)執(zhí)行以下操作:
一個(gè)常見的 jq 實(shí)現(xiàn)思路是利用其 walk 函數(shù)進(jìn)行遞歸遍歷,并在不同數(shù)據(jù)類型上應(yīng)用相應(yīng)的轉(zhuǎn)換邏輯。以下是一個(gè)初步的 jq 腳本示例,它嘗試滿足上述所有需求:
jq 'walk( if type == "string" then (sub("^[[:space:]]+"; "") | sub("[[:space:]]+$"; "") | if . == "true" then . |= true else . end | if . == "false" then . |= false else . end) elif type == "object" then with_entries(select(.value | IN("",null, [], {}) | not) | .key |= sub("^[[:space:]]+"; "") | .key |= sub("[[:space:]]+$"; "") |select(.key | IN("") | not )) elif type == "array" then map(select(. | IN("",null, [], {}) | not)) else . end)'
腳本邏輯解析:
盡管此腳本功能完整,但在處理大型數(shù)據(jù)集時(shí),其 CPU 占用可能較高。這通常是由于 walk 函數(shù)的內(nèi)部實(shí)現(xiàn)效率,或者在每個(gè)節(jié)點(diǎn)上重復(fù)執(zhí)行復(fù)雜邏輯所致。
為了提升性能,特別是降低 CPU 消耗,我們可以采用一個(gè)更為高效的自定義 walk 函數(shù)。jq 的內(nèi)置 walk 在某些情況下可能不是最優(yōu)的,尤其是在處理對象時(shí)。以下是一個(gè)經(jīng)過優(yōu)化的 walk 函數(shù)定義:
def walk(f): def w: if type == "object" then . as $in | reduce keys_unsorted[] as $key ( {}; . + { ($key): ($in[$key] | w) } ) | f elif type == "array" then map( w ) | f else f end; w;
優(yōu)化點(diǎn)解析:
Easily find JSON paths within JSON objects using our intuitive Json Path Finder
將上述優(yōu)化的 walk 函數(shù)與我們之前的數(shù)據(jù)處理邏輯結(jié)合,構(gòu)成一個(gè)完整的、高效的 jq 腳本。首先定義 walk 函數(shù),然后調(diào)用它并傳入我們的清理和轉(zhuǎn)換邏輯。
def walk(f): def w: if type == "object" then . as $in | reduce keys_unsorted[] as $key ( {}; . + { ($key): ($in[$key] | w) } ) | f elif type == "array" then map( w ) | f else f end; w; walk( if type == "string" then (sub("^[[:space:]]+"; "") | sub("[[:space:]]+$"; "") | if . == "true" then . |= true else . end | if . == "false" then . |= false else . end) elif type == "object" then with_entries(select(.value | IN("",null, [], {}) | not) | .key |= sub("^[[:space:]]+"; "") | .key |= sub("[[:space:]]+$"; "") |select(.key | IN("") | not )) elif type == "array" then map(select(. | IN("",null, [], {}) | not)) else . end)
示例演示:
假設(shè)我們有以下輸入 JSON 數(shù)據(jù):
{ "key1": " value1 ", "key2": "", "key3": "true", "key4": "false", "key5": [], "key6": {}, "key7": null, "key8": { "nested_key": " nested_value ", "empty_object_key": {} }, "key9": [ "array_item_1", "", " array_item_2 ", [] ], " empty_key ": 123 }
運(yùn)行上述 jq 腳本后,將得到以下輸出:
{ "key1": "value1", "key3": true, "key4": false, "key8": { "nested_key": "nested_value" }, "key9": [ "array_item_1", "array_item_2" ] }
可以看到,所有空值(包括空字符串、空數(shù)組、空對象、null)、僅含空白的字符串以及空鍵都被移除。字符串值和鍵的首尾空白已被清理,并且 "true" 和 "false" 字符串已成功轉(zhuǎn)換為布爾類型。
jq 是處理 JSON 數(shù)據(jù)的強(qiáng)大工具,通過靈活運(yùn)用其內(nèi)置函數(shù)和自定義過濾器,可以實(shí)現(xiàn)復(fù)雜的轉(zhuǎn)換邏輯。對于性能敏感的應(yīng)用場景,理解 jq 內(nèi)部機(jī)制并優(yōu)化核心遞歸函數(shù)(如 walk)至關(guān)重要。本文提供的優(yōu)化 walk 函數(shù)和整合方案,旨在幫助您更高效地清理、轉(zhuǎn)換和標(biāo)準(zhǔn)化 JSON 數(shù)據(jù),從而降低 CPU 消耗,提升數(shù)據(jù)預(yù)處理的效率。
以上就是使用 jq 高效遞歸處理 JSON 數(shù)據(jù):去除空值、類型轉(zhuǎn)換與字符串清理的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個(gè)人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進(jìn)程會占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號