python json字符串类型的value换行方案
生活随笔
收集整理的這篇文章主要介紹了
python json字符串类型的value换行方案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
按照標準json語法,字符串類型的value是不能換行寫的.
例如,以下是錯誤的寫法
但是遇到了需要在json中寫代碼與服務器交互的情況,無奈只能這樣寫:
{"key":"var a = 1\nvar b = 2\n var c=a+b" }代碼行數少了還好,多了極其**,于是想辦法可以在json中換行寫代碼.
嘗試1: json5
JSON5號稱"JSON for Humans",相比標準json主要特點如下:
- 字符串value支持換行
- key可以不加""
- key和value可以使用’'代替""
- 支持注釋
- 二進制數值
栗子:
以下是一個合法的json5
優(yōu)點:現成
缺點:
-
換行需要用 \ \標識;
-
解析之后因為沒有了換行,代碼無法執(zhí)行,所以是達不到目的的;
解析之后的結果為
{"key":"var a = 1var b = 2var c=a+b" }嘗試2: 編寫自己的json解釋器
- 優(yōu)點: 可根據自己定義的規(guī)則解析數據
- 缺點: 成本高.
以下為用python實現的json解釋器,支持換行,目前沒有做完整的錯誤處理,請不要用于生產:
""" 遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流QQ群:778463939 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! Topic: 下降解析器 Desc : """ import re import collections# Token specification NUM = r'(?P<NUM>\d+)' STR_D = r'"(?P<STR_D>[^"]*?)"' STR_S = r'(?P<STR_S>\'.*?\')' COLON = r'(?P<COLON>:)' COMMA = r'(?P<COMMA>,)' LLB = r'(?P<LLB>\[)' RLB = r'(?P<RLB>\])' LDB = r'(?P<LDB>\{)' RDB = r'(?P<RDB>\})' WS = r'(?P<WS>\s+)' NULL = r'(?P<NULL>null)' FALSE = r'(?P<FALSE>false)' TRUE = r'(?P<TRUE>true)'master_pat = re.compile('|'.join([NUM, STR_D, STR_S, LLB, RLB,LDB, RDB, COLON, COMMA, FALSE, TRUE, NULL, WS]), re.M | re.S) # Tokenizer Token = collections.namedtuple('Token', ['type', 'value'])def generate_tokens(text):scanner = master_pat.scanner(text)for m in iter(scanner.match, None):tok = Token(m.lastgroup, m.group())if tok.type != 'WS':yield tokdef simple_join(text):li = []for t in generate_tokens(text):res = t[1]if t[0] == "STR_S":res = t[1].replace("'", "\"")elif t[0].startswith("STR_"):res = t[1].replace("\n", "\\n").replace("\r\n", "\\n")li.append(str(res))return "".join(li)class Evaluator:def __init__(self, text):self.text = textdef parse(self):self.tokens = generate_tokens(self.text)self.nexttok = next(self.tokens, None)self._advance()return self._parse()def _advance(self):'''Advance one token ahead'''self.tok, self.nexttok = self.nexttok, next(self.tokens, None)def _parse(self):if self.tok[0] == "LLB":return self.get_list()if self.tok[0] == "LDB":return self.get_dict()if self.tok[0].startswith("STR_"):return self.tok[1].strip('"')if self.tok[0] == "NUM":return int(self.tok[1])if self.tok[0] == "NULL":return Noneif self.tok[0] == "FALSE":return Falseif self.tok[0] == "TRUE":return Trueraise Exception("未知token:{}".format(self.tok[1]))def get_dict(self):"""{ 開頭中間內容必須為 k:v,結尾必須為 }"""res = {}self._advance()# }if self.tok[0] == "RDB":return {}def parse_value():if not self.tok[0].startswith("STR_"):raise Exception(f"KEY需是字符串形式,{self.tok[1]}")new_key = self._parse()self._advance()if self.tok[0] != "COLON":raise Exception("KEY和VALUE需用:分割")self._advance()res[new_key] = self._parse()self._advance()parse_value()while self.tok[0] == "COMMA":self._advance()parse_value()return resdef get_list(self):res = []self._advance()# }if self.tok[0] == "RLB":return []def parse_value():if self.tok[0] in ["NUM", "STR_D", "STR_S", "NULL", "FALSE", "TRUE"]:res.append(self._parse())elif self.tok[0] == "LLB":res.append(self.get_list())elif self.tok[0] == "LDB":res.append(self.get_dict())parse_value()self._advance()while self.tok[0] == "COMMA":self._advance()parse_value()self._advance()return resif __name__ == '__main__':text = """{"k1":1,"k2":"v2","is_true":true,"is_none":null,"k2":"v2","k3":{"a1":"a1","a2":"a2","code":"var code = 0code = 1"},"list":[1,2,3,4]}"""# test(text)e = Evaluator(text)res = e.parse()print(res) #{'k1': 1, 'k2': 'v2', 'is_true': True, 'is_none': None, 'k3': {'a1': 'a1', 'a2': 'a2', 'code': '\n var code = 0\n code = 1\n '}, 'list': [1, 2, 3, 4]}嘗試3: 全局替換 \n 為 \n
優(yōu)點:簡單粗暴
{"key":" var a = 1 var b = 2 var c=a+b" }替換之后的結果為
{"key":"\nvar a = 1\nvar b = 2\n var c=a+b" }缺點:雖然寫的時候有換行,但是上傳到服務器再查詢的時候只能看到\n,依然缺乏可讀性;
嘗試4(最終采用方案):
結合UI將json生成樹狀節(jié)點,將代碼類型的value單獨顯示.
優(yōu)點
- 難度一般
- 按常規(guī)方式解析json
- 上傳到服務器再查詢的時候也能看到換行.
總結
以上是生活随笔為你收集整理的python json字符串类型的value换行方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 归并排序,合并有序数组,逆
- 下一篇: python:关于py文件之间相互imp