Skip to content

Commit e520b6f

Browse files
committed
Add support for chars, sets and ordered table. Re-benchmark.
1 parent 9395dd9 commit e520b6f

File tree

5 files changed

+83
-7
lines changed

5 files changed

+83
-7
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ Currently the Nim standard module first parses or serializes json into JsonNodes
1717

1818
Another speed up comes from not using `StringStream`. Stream has a function dispatch overhead because it has to be able to switch between `StringStream` or `FileStream` at runtime. Jsony skips the overhead and just directly reads or writes to memory buffers.
1919

20-
Another speed up comes from parsing and readings its own numbers directly from memory buffer. This allows it to by pass `string` allocations that `parseInt` or `$` create.
20+
Another speed up comes from parsing and readings its own numbers directly from memory buffer. This allows it to bypass `string` allocations that `parseInt` or `$` create.
2121

2222
### Parse speed.
2323
```
2424
name ............................... min time avg time std dv times
25-
treeform/jsony ..................... 6.311 ms 9.688 ms ±3.301 x100
25+
treeform/jsony ..................... 6.724 ms 12.047 ms ±3.694 x100
2626
status-im/nim-json-serialization ... 7.119 ms 14.276 ms ±2.033 x100
2727
nim std/json ...................... 24.141 ms 38.741 ms ±5.417 x100
2828
planetis-m/eminim ................. 10.974 ms 18.355 ms ±3.994 x100
@@ -43,11 +43,14 @@ Note: If you find a faster nim json parser or serializer let me know!
4343
## Can parse or serializer most types:
4444

4545
* numbers and strings
46+
* seq and arrays
4647
* objects and ref objects
4748
* enums
4849
* tuples
49-
* seq and arrays
50-
* tables
50+
* characters
51+
* `HashTable`s and `OrderedTable`s
52+
* `HashSet`s and `OrderedSet`s
53+
* json nodes
5154
* and `parseHook()` enables you to parse any type!
5255

5356
## Not strict.

src/jsony.nim

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import jsony/objvar, strutils, tables, unicode, json
1+
import jsony/objvar, strutils, tables, sets, unicode, json
22

33
type JsonError* = object of ValueError
44

@@ -7,13 +7,18 @@ const whiteSpace = {' ', '\n', '\t', '\r'}
77
when defined(release):
88
{.push checks: off.}
99

10+
type SomeTable*[K, V] = Table[K, V] | OrderedTable[K, V] |
11+
TableRef[K, V] | OrderedTableRef[K, V]
12+
1013
proc parseHook*[T](s: string, i: var int, v: var seq[T])
1114
proc parseHook*[T: enum](s: string, i: var int, v: var T)
1215
proc parseHook*[T: object|ref object](s: string, i: var int, v: var T)
13-
proc parseHook*[T](s: string, i: var int, v: var Table[string, T])
16+
proc parseHook*[T](s: string, i: var int, v: var SomeTable[string, T])
17+
proc parseHook*[T](s: string, i: var int, v: var SomeSet[T])
1418
proc parseHook*[T: tuple](s: string, i: var int, v: var T)
1519
proc parseHook*[T: array](s: string, i: var int, v: var T)
1620
proc parseHook*(s: string, i: var int, v: var JsonNode)
21+
proc parseHook*(s: string, i: var int, v: var char)
1722
1823
template error(msg: string, i: int) =
1924
## Shortcut to raise an exception.
@@ -147,6 +152,13 @@ proc parseHook*(s: string, i: var int, v: var string) =
147152
inc i
148153
eatChar(s, i, '"')
149154

155+
proc parseHook*(s: string, i: var int, v: var char) =
156+
var str: string
157+
s.parseHook(i, str)
158+
if str.len != 1:
159+
error("String can't fit into a char.", i)
160+
v = str[0]
161+
150162
proc parseHook*[T](s: string, i: var int, v: var seq[T]) =
151163
## Parse seq.
152164
eatChar(s, i, '[')
@@ -316,8 +328,10 @@ proc parseHook*[T: object|ref object](s: string, i: var int, v: var T) =
316328
postHook(v)
317329
eatChar(s, i, '}')
318330

319-
proc parseHook*[T](s: string, i: var int, v: var Table[string, T]) =
331+
proc parseHook*[T](s: string, i: var int, v: var SomeTable[string, T]) =
320332
## Parse an object.
333+
when compiles(new(v)):
334+
new(v)
321335
eatChar(s, i, '{')
322336
while i < s.len:
323337
eatSpace(s, i)
@@ -335,6 +349,22 @@ proc parseHook*[T](s: string, i: var int, v: var Table[string, T]) =
335349
break
336350
eatChar(s, i, '}')
337351
352+
proc parseHook*[T](s: string, i: var int, v: var SomeSet[T]) =
353+
## Parse HashSet.
354+
eatSpace(s, i)
355+
eatChar(s, i, '[')
356+
while true:
357+
eatSpace(s, i)
358+
if i < s.len and s[i] == ']':
359+
break
360+
var e: T
361+
parseHook(s, i, e)
362+
v.incl(e)
363+
eatSpace(s, i)
364+
if i < s.len and s[i] == ',':
365+
inc i
366+
eatChar(s, i, ']')
367+
338368
proc parseHook*(s: string, i: var int, v: var JsonNode) =
339369
## Parses a regular json node.
340370
eatSpace(s, i)
@@ -592,6 +622,16 @@ proc dumpHook*(s: var string, v: ref object) =
592622
else:
593623
s.dumpHook(v[])
594624

625+
proc dumpHook*[T](s: var string, v: HashSet[T]|OrderedSet[T]) =
626+
s.add '['
627+
var i = 0
628+
for e in v:
629+
if i != 0:
630+
s.add ','
631+
s.dumpHook(e)
632+
inc i
633+
s.add ']'
634+
595635
proc dumpHook*(s: var string, v: JsonNode) =
596636
## Dumps a regular json node.
597637
case v.kind:

tests/test_char.nim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import jsony
2+
3+
doAssert """ "a" """.fromJson(char) == 'a'
4+
doAssert """["a"]""".fromJson(seq[char]) == @['a']
5+
doAssert """["a", "b", "c"]""".fromJson(seq[char]) == @['a', 'b', 'c']
6+
doAssert 'a'.toJson() == """"a""""
7+
doAssert 'b'.toJson() == """"b""""

tests/test_sets.nim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import jsony, sets
2+
3+
block:
4+
let
5+
s1 = toHashSet([9, 5, 1])
6+
s2 = toOrderedSet([3, 5, 7])
7+
8+
doAssert s1.toJson() == "[9,1,5]"
9+
doAssert s2.toJson() == "[3,5,7]"
10+
11+
doAssert s1.toJson.fromJson(type(s1)) == s1
12+
doAssert s2.toJson.fromJson(type(s2)) == s2

tests/test_tables.nim

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,17 @@ block:
3333
doAssert v["a"].color == "red"
3434
doAssert v["b"].color == "green"
3535
doAssert v["c"].color == "blue"
36+
37+
block:
38+
type Entry = object
39+
color: string
40+
var s = """{
41+
"a": {"color":"red"},
42+
"b": {"color":"green"},
43+
"c": {"color":"blue"}
44+
}"""
45+
var v = s.fromJson(OrderedTableRef[string, Entry])
46+
doAssert v.len == 3
47+
doAssert v["a"].color == "red"
48+
doAssert v["b"].color == "green"
49+
doAssert v["c"].color == "blue"

0 commit comments

Comments
 (0)