我找到了一個使Vim能夠解析JSON的插件。我需要將VimScript字典導出爲JSON。目前,我只是用:將Vimscript Dictionary導出爲JSON
let str = string(dict)
substitute(str, "'", '"', 'g')
這是工作,但勢必打破,當我運行與嵌入式引號字典。什麼是更好的方法?
我找到了一個使Vim能夠解析JSON的插件。我需要將VimScript字典導出爲JSON。目前,我只是用:將Vimscript Dictionary導出爲JSON
let str = string(dict)
substitute(str, "'", '"', 'g')
這是工作,但勢必打破,當我運行與嵌入式引號字典。什麼是更好的方法?
的WebAPI.vim插件有一個JSON解析器和編碼器:
:let jsonString = webapi#json#encode({...})
我寫了一個小函數echo
的json字符串,用"
雙引號轉義。不知道它是否適合你的需要:
function! ToJson(input)
if type(a:input) == type({})
echo "{"
let di = 0
for key in keys(a:input)
let di += 1
if type(key) == type('')
echo '"'.substitute(key, '"', '\\"','g').'":'
else
echo '"'.key.'":'
endif
call ToJson(a:input[key])
echo di<len(a:input)? "," : ""
endfor
echo "}"
elseif type(a:input) == type([])
echo "["
let li = 0
for e in a:input
let li += 1
call ToJson(e)
if li<len(a:input)
echo ","
endif
endfor
echo "]"
elseif type(a:input) == type('')
echo '"'.substitute(a:input, '"', '\\"','g').'"'
else
echo '"'.a:input.'"'
endif
endfunction
的字典,如:
let d1={'one':'"""', 'two':123, 333:['11',22,'"_"_"'], 'four':"''"}
將輸出爲:
{
"four":
"''"
,
"one":
"\"\"\""
,
"two":
"123"
,
"333":
[
"11"
,
"22"
,
"\"_\"_\""
]
}
我沒有做太多調試/測試。也格式看起來不是很好,但我猜你不關心,因爲你使用string()
格式...
上面的輸出可以被格式化成(通過在線JSON格式):
{
"four":"''",
"one":"\"\"\"",
"two":"123",
"333":[
"11",
"22",
"\"_\"_\""
]
}
希望它有幫助。
我不確定這應該是一個單獨的答案,編輯@肯特的答案,或評論@肯特的答案。這裏是一個版本@肯特與一些簡化功能:
function! ToJson(input)
let json = ''
if type(a:input) == type({})
let json .= "{"
let di = 0
for key in keys(a:input)
let di += 1
let json .= '"'.escape(key, '"').'":'
let json .= ToJson(a:input[key])
let json .= di<len(a:input)? "," : ""
endfor
let json .= "}"
elseif type(a:input) == type([])
let json .= "["
let li = 0
for e in a:input
let li += 1
let json .= ToJson(e)
if li<len(a:input)
let json .= ","
endif
endfor
let json .= "]"
else
let json .= '"'.escape(a:input, '"').'"'
endif
return json
endfunction
相反呼應的結果,它返回它作爲一個字符串。此外,我使用escape()
而不是substitute()
。最後,我認爲(檢查這個!)可以安全地使用escape()
,因爲我沒有首先檢查參數是否是字符串。
這是一個較短的版本,使用map()
。我不知道遞歸的深度對於這個版本或其他版本是否更重要,但是如果您的輸入足夠大以至於很重要,那麼如果我們讓map()
處理遞歸可能會更快。
function! ToJson(input)
let json = ''
if type(a:input) == type({})
let parts = copy(a:input)
call map(parts, '"\"" . escape(v:key, "\"") . "\":" . ToJson(v:val)')
let json .= "{" . join(values(parts), ",") . "}"
elseif type(a:input) == type([])
let parts = map(copy(a:input), 'ToJson(v:val)')
let json .= "[" . join(parts, ",") . "]"
else
let json .= '"'.escape(a:input, '"').'"'
endif
return json
endfunction
使用任一版本,除了空白外,我得到了和@ Kent函數相同的結果。我還沒有比@ Kent的d1
更復雜的測試它。使用deepcopy()
可能比copy()
更安全。
+1你的答案。我也嘗試使用'escape()',但是我可能會犯一些愚蠢的錯誤,在輸出中沒有'slash'。我沒有進一步測試並使用'sub ..()'。同樣對於地圖,我也想到了它,但是我需要在每個遞歸步驟中使用'deepcopy'這個對象,並且我認爲如果字典具有相對更多的嵌套層次,它可能會成爲一些問題。但我沒有深思。 – Kent
基於@benjifisher答案,我發展ToJson
。
縮進是hacky,但主要是工作。
" Inspect variables
"
" input: variable
" level: actual level of nest
" max: maximum level of nest let json = ''
function! ToJson(input, level, max)
if a:level < a:max
if type(a:input) == type({})
let parts = copy(a:input)
call map(parts, '"\"" . escape(v:key, "\"") . "\":" . ToJson(v:val, ' . (a:level+1) . ',' . a:max . ")")
let space = repeat(" ", a:level)
let json .= space . " {\r\n " . space . join(values(parts), ",\r\n " . space) . "\r\n" . space ." }"
elseif type(a:input) == type([])
let parts = map(copy(a:input), 'ToJson(v:val,' . (a:level+1) . ',' . a:max . ')')
let json .= "[" . join(parts, ",\r\n") . "]\r\n"
elseif type(a:input) == type(function("tr"))
let dictFunc = substitute(string(a:input), "function('\\(.\\+\\)')", "\\1", "")
if dictFunc+0 > 0
let funcName = '{' . dictFunc . '}'
else
let funcName = a:input
endif
let json .= '"'.escape(genutils#ExtractFuncListing(funcName, 0, 0), '"') . "\""
else
let json .= '"'.escape(a:input, '"') . "\""
endif
else
try
let json .= '"' . escape(string(a:input), '"') . "\""
catch
"string() can throw an E724 (too much nest)
let json .= '"' . escape(keys(a:input), '"') . "\""
endtry
endif
return json
endfunction
要顯示函數定義,你需要依賴從https://github.com/vim-scripts/genutils:
https://github.com/vim-scripts/genutils/blob/master/autoload/genutils.vim#L57
忽略的那部分,如果它不適合你,是應該在視覺VIM調試vim-breakpts用於檢查複雜的變量
兩年半後,我的原始答案,有一個更簡單的替代:升級到Vim 8和使用json_encode()
或(如果你不需要嚴格t JSON)js_encode()
。
什麼插件? JSON-to-Vim插件的意義何在? – romainl