Skip to content

Commit 4f843c5

Browse files
committed
Web.JSON: Convert encoding. Add 'from_encoding' setting to encode().
1 parent 348f1a1 commit 4f843c5

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

autoload/vital/__vital__/Web/JSON.vim

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ function! s:decode(json, ...) abort
110110
\ 'use_token': 0,
111111
\ 'allow_nan': 1,
112112
\}, get(a:000, 0, {}))
113-
let json = join(split(a:json, "\n"), '')
113+
let json = iconv(a:json, 'utf-8', &encoding)
114+
let json = join(split(json, "\n"), '')
114115
let json = substitute(json, '\\u34;', '\\"', 'g')
115116
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=s:string.nr2enc_char("0x".submatch(1))', 'g')
116117
if settings.allow_nan
@@ -138,13 +139,19 @@ function! s:encode(val, ...) abort
138139
let settings = extend({
139140
\ 'indent': 0,
140141
\ 'allow_nan': 1,
142+
\ 'from_encoding': &encoding,
141143
\}, get(a:000, 0, {})
142144
\)
145+
return s:_encode(a:val, settings)
146+
endfunction
147+
148+
function! s:_encode(val, settings) abort
143149
let t = type(a:val)
144150
if t == 0
145151
return a:val
146152
elseif t == 1
147-
let s = substitute(a:val, '[\x01-\x1f\\"]', '\=s:control_chars[submatch(0)]', 'g')
153+
let s = iconv(a:val, a:settings.from_encoding, 'utf-8')
154+
let s = substitute(s, '[\x01-\x1f\\"]', '\=s:control_chars[submatch(0)]', 'g')
148155
return '"' . s . '"'
149156
elseif t == 2
150157
if s:const.true == a:val
@@ -158,12 +165,12 @@ function! s:encode(val, ...) abort
158165
return string(a:val)
159166
endif
160167
elseif t == 3
161-
return s:_encode_list(a:val, settings)
168+
return s:_encode_list(a:val, a:settings)
162169
elseif t == 4
163-
return s:_encode_dict(a:val, settings)
170+
return s:_encode_dict(a:val, a:settings)
164171
elseif t == 5
165172
let val = string(a:val)
166-
if settings.allow_nan
173+
if a:settings.allow_nan
167174
let val = get(s:float_constants, val, val)
168175
elseif has_key(s:float_constants, val)
169176
throw 'vital: Web.JSON: Invalid float value: ' . val
@@ -181,7 +188,7 @@ function! s:_encode_list(val, settings) abort
181188
if empty(a:val)
182189
return '[]'
183190
elseif !a:settings.indent
184-
let encoded_candidates = map(copy(a:val), 's:encode(v:val, a:settings)')
191+
let encoded_candidates = map(copy(a:val), 's:_encode(v:val, a:settings)')
185192
return printf('[%s]', join(encoded_candidates, ','))
186193
else
187194
let previous_indent = get(a:settings, '_previous_indent')
@@ -191,7 +198,7 @@ function! s:_encode_list(val, settings) abort
191198
\})
192199
let encoded_candidates = map(
193200
\ copy(a:val),
194-
\ printf('''%s'' . s:encode(v:val, ns)', repeat(' ', indent)),
201+
\ printf('''%s'' . s:_encode(v:val, ns)', repeat(' ', indent)),
195202
\)
196203
return printf(
197204
\ "[\n%s\n%s]",
@@ -208,7 +215,7 @@ function! s:_encode_dict(val, settings) abort
208215
return '{}'
209216
elseif !a:settings.indent
210217
let encoded_candidates = map(keys(a:val),
211-
\ 's:encode(v:val, a:settings) . '':'' . s:encode(a:val[v:val], a:settings)'
218+
\ 's:_encode(v:val, a:settings) . '':'' . s:_encode(a:val[v:val], a:settings)'
212219
\)
213220
return printf('{%s}', join(encoded_candidates, ','))
214221
else
@@ -219,7 +226,7 @@ function! s:_encode_dict(val, settings) abort
219226
\})
220227
let encoded_candidates = map(keys(a:val),
221228
\ printf(
222-
\ '''%s'' . s:encode(v:val, ns) . '': '' . s:encode(a:val[v:val], ns)',
229+
\ '''%s'' . s:_encode(v:val, ns) . '': '' . s:_encode(a:val[v:val], ns)',
223230
\ repeat(' ', indent),
224231
\ ),
225232
\)

test/Web/JSON.vimspec

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,22 @@ Describe Web.JSON
3434
Assert Equals(JSON.decode('"\b\t\n\u000b\f\r\u000e\u000f"'), "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")
3535
Assert Equals(JSON.decode('"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"'), "\x10\x11\x12\x13\x14\x15\x16\x17")
3636
Assert Equals(JSON.decode('"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"'), "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f")
37-
" there should be iconv tests as well
37+
" multibyte
38+
Assert Equals(JSON.decode('"s¢cĴgё"'), "s¢cĴgё")
39+
End
40+
41+
It decodes strings with character encoding
42+
let expected_utf8 = "sあc漢g"
43+
Assert Equals(JSON.decode('"sあc漢g"'), expected_utf8)
44+
45+
let expected_sjis = iconv("sあc漢g", 'utf-8', 'sjis')
46+
try
47+
let &encoding = 'sjis'
48+
let res = JSON.decode('"sあc漢g"')
49+
finally
50+
let &encoding = 'utf-8'
51+
endtry
52+
Assert Equals(res, expected_sjis)
3853
End
3954

4055
It decodes lists
@@ -115,7 +130,25 @@ Describe Web.JSON
115130
Assert Equals(JSON.encode("\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"), '"\b\t\n\u000b\f\r\u000e\u000f"')
116131
Assert Equals(JSON.encode("\x10\x11\x12\x13\x14\x15\x16\x17"), '"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"')
117132
Assert Equals(JSON.encode("\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"), '"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"')
118-
" there should be iconv tests as well
133+
" multibyte
134+
Assert Equals(JSON.encode("s¢cĴgё"), '"s¢cĴgё"')
135+
End
136+
137+
It encodes strings with character encoding
138+
let str_utf8 = "sあc漢g"
139+
Assert Equals(JSON.encode(str_utf8), '"sあc漢g"')
140+
141+
let str_sjis = iconv("sあc漢g", 'utf-8', 'sjis')
142+
try
143+
let &encoding = 'sjis'
144+
let res = JSON.encode(str_sjis)
145+
finally
146+
let &encoding = 'utf-8'
147+
endtry
148+
Assert Equals(res, '"sあc漢g"')
149+
150+
let s = { 'from_encoding': 'sjis' }
151+
Assert Equals(JSON.encode(str_sjis, s), '"sあc漢g"')
119152
End
120153

121154
It encodes lists

0 commit comments

Comments
 (0)