最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中優(yōu)雅地處理JSON5文件的方法詳解

 更新時間:2024年04月23日 08:49:14   作者:xiemingtian  
JSON5 是 JSON 的一個超集,通過引入部分 ECMAScript 5.1 的特性來擴展 JSON 的語法,以減少 JSON 格式的某些限制,同時,保持兼容現(xiàn)有的 JSON 格式,本文給大家介紹了Python中如何優(yōu)雅地處理 JSON5 文件,需要的朋友可以參考下

JSON5 概述

JSON5 是 JSON 的一個超集,通過引入部分 ECMAScript 5.1 的特性來擴展 JSON 的語法,以減少 JSON 格式的某些限制。同時,保持兼容現(xiàn)有的 JSON 格式。從官網(wǎng)作者介紹來看,JSON5 注重的是更人性化的編寫和維護,一般用于軟件的配置文件場景。

JSON5 拓展了 JSON 的能力,支持以下特性:

  • 注釋

  • 尾隨逗號

  • 單引號

  • 字符串字面量

  • 數(shù)字 (包括 Infinity, NaN, hexadecimal)

  • 對象/數(shù)組字面量

  • 多行字符串

格式官方文檔 spec.json5.org/

遇到的問題

最近團隊開始對接華為鴻蒙系統(tǒng),在鴻蒙工程中,配置文件都是 json5 文件格式。例如存儲 APP 信息的 app.json5

{
  "app": {
    // 包名
    "bundleName": "com.xxx.sample",
    // 廠家信息
    "vendor": "sample",
    // 版本號
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_launcher",
    "label": "$string:app_name",
    "generateBuildHash": true
  }
}

JSON5 文件中會存儲數(shù)據(jù)信息和注釋信息,有助于在閱讀的時候了解數(shù)據(jù)結(jié)構(gòu)。

需求:腳本修改 JSON5 文件時保留注釋信息

需求:在 CD 構(gòu)建時,根據(jù)傳入的版本號修改 app.json5 中的版本號信息,然后將修改的文件提交到對應(yīng)的版本分支上。

處理方式:因為是 python 的腳本,所以就找了 python 中可以操作 json5 的庫,首先就是最常見的 json5 庫,它提供與標準 json 庫類似的 API,可以讀寫 json5 文件,例如下面的例子

import json5

data = json5.load(open('app.json5','r'))
print(json5.dumps(data, indent=4))
// 輸出結(jié)果
{
    "app": {    
        "bundleName": "com.xxx.sample",
        "vendor": "sample",
        "versionCode": 1000000,
        "versionName": "1.0.0",
        "icon": "$media:app_launcher",
        "label": "$string:app_name",
        "generateBuildHash": true    
    }
}

可以看到雖然 API 可以正確的解析和輸出文件數(shù)據(jù),但是注釋信息卻沒有了。使用官方推薦的 nodejs 版本 json5 庫也是一樣的結(jié)果。也有人開 issue 提需求是否可以提供 API 可以保留注釋信息,但是作者最終還是暫時婉拒了這個需求

后續(xù)雖然有人提交了支持這個 feature 的 PR,但是也是遲遲沒有合入。所以目前來說較為官方的庫都是沒有支持讀寫 json5 文件時保留注釋信息的。

雖然在搜索解決方案的時候,也有人提出說直接使用一個字段(例如"__comment__")存儲注釋信息,但是個人認為這是非常不優(yōu)雅的:明明 JSON5 推出就是支持注釋的,最終又要回退到 JSON。

解決方式

雖然官方庫沒有支持讀寫時保留注釋信息,但是還是有部分擴展庫是支持的。這些擴展庫也在 JSON5 的 Github 的 Wiki 中 In-the-Wild 部分列舉了出來。

json-five

其中 json-five 這個庫支持讀寫 JSON5 文件時保留注釋信息。

下面是官方提供的一個 demo

from json5.loader import loads, ModelLoader
from json5.dumper import dumps, ModelDumper
from json5.model import BlockComment
json_string = """{"foo": "bar"}"""model = loads(json_string, loader=ModelLoader())print(model.value.key_value_pairs[0].value.wsc_before)  # [' ']
model.value.key_value_pairs[0].key.wsc_before.append(BlockComment("/* comment */"))
dumps(model, dumper=ModelDumper()) # '{/* comment */"foo": "bar"}'

可以看出,雖然 json-five 支持了保留注釋信息,但是在數(shù)據(jù)的操作上非常麻煩,基本不能像使用 json 庫時將數(shù)據(jù)當(dāng)做 dict 進行操作,這樣很不優(yōu)雅。

擴展 json-five

于是對現(xiàn)有數(shù)據(jù)結(jié)構(gòu)進行了擴展,支持[]操作符進行獲取或者賦值,簡化 json5 操作流程。

# -*- coding: UTF-8 -*-
'''
支持保留注釋和格式的JSON5處理工具
'''
# pip3 install json-five
import json5
from json5.dumper import modelize
from json5.model import JSONArray, JSONObject, String, JSONText, Value, KeyValuePair, walk

# 重寫JSONObject的__getitem__方法,支持通過字符串獲取值,如果不存在則返回None
def _find(self, key):
    if isinstance(key, str) and isinstance(self, JSONObject):
        for item in self.key_value_pairs:
            if isinstance(item.key, String):
                if item.key.characters == key:
                    return item.value
    elif isinstance(key, int) and isinstance(self, JSONArray):
        return self.values[key]
    elif isinstance(self, JSONText):
        return self.value[key]
    return None

# 重寫JSONObject的__setitem__方法,支持通過字符串設(shè)置值,如果不存在則拋出異常
def _jsonobj_set(self: JSONObject, key: str, value: Value):
    new_item = KeyValuePair(modelize(key), value)
    for index in range(len(self.key_value_pairs)):
        item = self.key_value_pairs[index]
        if isinstance(item.key, String):
            if item.key.characters == key:
                old_value = self.values[index]
                new_item.value.wsc_after = old_value.wsc_after
                new_item.value.wsc_before = old_value.wsc_before
                new_item.value._tok = old_value._tok
                new_item.value._end_tok = old_value._end_tok
                self.values[index] = new_item.value
                return
    raise KeyError(key)
    # self.keys.append(new_item.key)
    # self.values.append(new_item.value)

# 重寫JSONArray的__setitem__方法,支持通過整數(shù)設(shè)置值,如果不存在則拋出異常,如果存在則覆蓋原值
def _jsonarray_set(self: JSONArray, index: int, value: Value):
    self.values[index] = value

# 重寫JSONObject的str_keys方法,支持返回所有字符串類型的keys,如果不存在則返回[]
def _jsonobj_str_keys(self: JSONObject):
    return [item.characters for item in self.keys if isinstance(item, String)]

JSONObject.__getitem__ = _find
JSONObject.__setitem__ = _jsonobj_set
JSONObject.str_keys = _jsonobj_str_keys
JSONArray.__getitem__ = _find
JSONArray.__setitem__ = _jsonarray_set
JSONText.__getitem__ = _find

# 加載JSON5文件,保留注釋和格式,返回一個Model對象
def loadjson5_with_comment(path: str):
    return json5.load(open(path, 'r'), loader=json5.loader.ModelLoader())

# 保存JSON5文件,保留注釋和格式
def savejson5_with_comment(data, path: str):
    return json5.dump(data, open(path, 'w'), dumper=json5.dumper.ModelDumper())

# 尋找所有JSONObject中key為keyword的對象,返回一個列表,如果不存在則返回[]
def find_jsonobjects(model, keyword: str) -> list[JSONObject]:
    items = []
    for item in walk(model):
        if isinstance(item, JSONObject):
            for key in item.keys:
                if isinstance(key, String) and key.characters == keyword:
                    items.append(item)
    return items

最終實現(xiàn)以下效果,最大限度地保留的文件格式和注釋信息,優(yōu)雅地滿足了需求

file_path = 'app.json5'
model = loadjson5_with_comment(file_path)
model['app']['versionName'] = modelize('1.1.1')
savejson5_with_comment(model, file_path)
# 修改后文件內(nèi)容
{
  "app": {
    // 包名
    "bundleName": "com.xxx.sample",
    // 廠家信息
    "vendor": "sample",
    // 版本號
    "versionCode": 1000000,
    "versionName": '1.1.1',
    "icon": "$media:app_launcher",
    "label": "$string:app_name",
    "generateBuildHash": true
  }
}

其他庫

In-the-Wild 中可以看到有很多庫支持 json5,但是測試前面的幾個 python 和 js 的庫,目前只有 json-five 這個支持保留注釋信息(也可能是我使用姿勢問題?)

總結(jié)

JSON5 作為 JSON 的擴展,提供了更人性化的語法,非常適合靜態(tài)配置文件場景,可以目前官方的庫 API 讀寫文件時不支持保留注釋信息(往往可能是配置文件中關(guān)鍵信息),在一些自動化場景稍顯不便。

雖然目前可以通過三方庫+擴展的方式達到一個基本可用的狀態(tài),還是希望官方能對此能力進行支持,讓 JSON5 的處理更優(yōu)雅~

以上就是Python中優(yōu)雅地處理JSON5文件的方法詳解的詳細內(nèi)容,更多關(guān)于Python處理JSON5文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python機器學(xué)習(xí)NLP自然語言處理基本操作詞向量模型

    Python機器學(xué)習(xí)NLP自然語言處理基本操作詞向量模型

    本文是Python機器學(xué)習(xí)NLP自然語言處理系列文章,帶大家開啟一段學(xué)習(xí)自然語言處理 (NLP) 的旅程。本篇文章主要學(xué)習(xí)NLP自然語言處理基本操作詞向量模型
    2021-09-09
  • Python3 用什么IDE開發(fā)工具比較好

    Python3 用什么IDE開發(fā)工具比較好

    這篇文章主要介紹了Python3 用什么IDE開發(fā)工具比較好,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • Matplotlib實現(xiàn)各種條形圖繪制

    Matplotlib實現(xiàn)各種條形圖繪制

    這篇文章主要介紹了Matplotlib實現(xiàn)各種條形圖繪制,文章通過利用 plt.bar 方法實現(xiàn)各種條形圖繪制,內(nèi)容詳細具有一定的參考價值,需要的小伙伴可以參考一下
    2022-03-03
  • sklearn中的交叉驗證的實現(xiàn)(Cross-Validation)

    sklearn中的交叉驗證的實現(xiàn)(Cross-Validation)

    這篇文章主要介紹了sklearn中的交叉驗證的實現(xiàn)(Cross-Validation),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Python的Bottle框架的一些使用技巧介紹

    Python的Bottle框架的一些使用技巧介紹

    這篇文章主要介紹了Python的Bottle框架的一些使用技巧,文中用代碼舉例介紹了這些技巧用到的特性,需要的朋友可以參考下
    2015-04-04
  • 解決ImportError: cannot import name ‘Imputer‘的問題

    解決ImportError: cannot import name ‘Imput

    您遇到的ImportError: cannot import name ‘Imputer‘錯誤提示表明您嘗試導(dǎo)入一個名為’Imputer’的模塊或類,但是該模塊或類無法找到,本文小編給大家介紹了如何解決這個問題,需要的朋友可以參考下
    2023-10-10
  • Python加速運行8個優(yōu)化技巧分享

    Python加速運行8個優(yōu)化技巧分享

    Python 是一種腳本語言,相比 C/C++ 這樣的編譯語言,在效率和性能方面存在一些不足,但是,有很多時候,Python 的效率并沒有想象中的那么夸張,本文對一些 Python 代碼加速運行的技巧進行整理,大家可以根據(jù)需求進行選擇
    2025-06-06
  • Python+OpenCV實現(xiàn)相機標定的方法詳解

    Python+OpenCV實現(xiàn)相機標定的方法詳解

    opencv中內(nèi)置了張正友的棋盤格標定法,通過一些姿態(tài)各異的棋盤格圖像,可以標定相機的內(nèi)外參數(shù),本文為大家介紹OpenCV進行相機標定的具體方法,希望對大家有所幫助
    2023-05-05
  • Python File(文件) 方法整理

    Python File(文件) 方法整理

    在本篇文章中我們給大家整理了關(guān)于Python File(文件) 的用法以及相關(guān)知識點,有興趣的朋友們學(xué)習(xí)下。
    2019-02-02
  • win10系統(tǒng)下Anaconda3安裝配置方法圖文教程

    win10系統(tǒng)下Anaconda3安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了win10系統(tǒng)下Anaconda3安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09

最新評論

崇州市| 尼玛县| 奉节县| 凯里市| 彝良县| 大厂| 中宁县| 鹤山市| 东港市| 蒙阴县| 永平县| 昆明市| 元阳县| 淳化县| 英吉沙县| 长子县| 彝良县| 开平市| 伊宁市| 五指山市| 新化县| 霍城县| 大关县| 天全县| 万山特区| 宣武区| 大洼县| 大埔区| 牟定县| 烟台市| 石家庄市| 察雅县| 余姚市| 盐源县| 淮北市| 边坝县| 新闻| 三台县| 涞水县| 建水县| 大名县|