Hi, my custom data type contains times.DateTime:
import options, tables, times
import deser_json
type
Data* = object
shifts*: OrderedTable[int64, Shift]
balance*: float
Shift* = object
quoted*: bool
date*: DateTime
description*: string
start*: Option[DateTime]
finish*: Option[DateTime]
breakTime*: Option[Duration]
rate*: float
qty: Option[float]
id*: int64
let shift = Shift(
quoted: true,
date: parse("2000-01-01", "yyyy-MM-dd"),
description: "abcdef",
start: none(DateTime),
finish: none(DateTime),
breakTime: none(Duration),
rate: 462.11,
qty: some(10.0),
id: getTime().toUnix()
)
var shifts: OrderedTable[int64, Shift]
shifts[shift.id] = shift
let data = Data(
shifts: shifts,
balance: 0.00
)
assert data == data.dumps().parse().to(Data)
When I try to serialize/deserialize my type I get the following error:
/home/adnan338/.choosenim/toolchains/nim-1.4.2/lib/pure/times.nim(2110, 39) Hint: 'parse' cannot raise 'Defect' [XCannotRaiseY]
/tmp/serde.nim(39, 8) template/generic instantiation of `assert` from here
/home/adnan338/.nimble/pkgs/deser_json-0.2.1/deser_json.nim(341, 8) template/generic instantiation of `dumps` from here
/home/adnan338/.nimble/pkgs/deser_json-0.2.1/deser_json.nim(296, 17) template/generic instantiation of `forSerFields` from here
/home/adnan338/.nimble/pkgs/deser-0.1.4/deser/templates.nim(8, 15) Error: attempting to call undeclared routine: 'hasCustomPragma'
I was using deserjson in this code, I also tried nimyaml and serializetools and they also failed for different reasons. What package should supoort my data type?
I tried deser_json and I get the same errors. I fixed hasCustomPragma with import macros but then I get m.tokens[pos].kind == JSMN_OBJECT ... I don't know how to get around that one.
If you want to use json (for easier debugging or compatibility) take a look at these libraries they pass my tests:
name ............................... min time avg time std dv times
treeform/jsony ..................... 1.531 ms 2.779 ms ±0.091 x100
status-im/nim-json-serialization ... 2.043 ms 3.448 ms ±0.746 x100
planetis-m/eminim .................. 5.951 ms 9.305 ms ±3.210 x100
disruptek/jason ................... 10.312 ms 13.471 ms ±3.107 x100
nim std/json ...................... 12.551 ms 19.419 ms ±4.039 x100
name ............................... min time avg time std dv times
treeform/jsony ..................... 6.724 ms 12.047 ms ±3.694 x100
status-im/nim-json-serialization ... 7.119 ms 14.276 ms ±2.033 x100
nim std/json ...................... 24.141 ms 38.741 ms ±5.417 x100
planetis-m/eminim ................. 10.974 ms 18.355 ms ±3.994 x100
https://github.com/treeform/jsony
But really if you want to go fast you might want a binary format instead of json:
name ............................... min time avg time std dv runs
treeform/flatty .................... 3.615 ms 3.712 ms ±0.084 x100
bingod/planetis-m .................. 6.632 ms 6.785 ms ±0.105 x100
disruptek/frosty ................... 9.133 ms 9.294 ms ±0.152 x100
treeform/jsony ..................... 7.746 ms 7.858 ms ±0.081 x100
treeform/flatty .................... 7.849 ms 11.745 ms ±0.157 x100
bingod/planetis-m binTo ............ 8.414 ms 13.114 ms ±5.822 x100
disruptek/frosty .................. 29.689 ms 30.109 ms ±0.309 x100
treeform/jsony .................... 60.054 ms 62.637 ms ±0.616 x100
https://github.com/treeform/flatty
If a library fails to work try another one... if my library fails to work open a issue on github.
Looking at date time more, I don't think DateTime is a good candidate for serializing because it contains pointers to functions that determine timezone. How do you want to handle the timezones? I would recommend just stocking with unix epoc (seconds from 1970) if you don't want to make your life x100 harder by dealing with timezone sterilization.
I don't usually use DateTime (I use the https://github.com/treeform/chrono), but here is what I got:
import times, flatty
proc toFlatty(s: var string, x: DateTime) =
s.toFlatty(x.toTime.toUnix)
proc fromFlatty(s: string, i: var int, x: var DateTime) =
var
unix: int64
s.fromFlatty(i, unix)
x = parse("1970-01-01", "yyyy-MM-dd", utc()) + initTimeInterval(seconds = unix.int)
var date = parse("2000-01-01", "yyyy-MM-dd", utc())
echo date
echo date.toFlatty().fromFlatty(type(date))
assert date == date.toFlatty().fromFlatty(type(date))