-
Notifications
You must be signed in to change notification settings - Fork 39
Description
I just posted this on nim forum too.
Using jsony 1.1.6
Nim 2.2.0 in Windows, 2.3.1 in ubuntu WSL
I'm trying to parse pairs of ints like (10,20) in json by using a custom parser and object variants. Eventually I want to do (1.23. 3.14), or ($var1, $var2), etc., so it should support ints, floats, and strings. Everything should be in double quotes so it's json compliant. There is a parsehook for JVal variant type which can hold int, float, or string, and another parsehook for JPoint. The JPoint is a pair of JVals. The JShape is either two JPoints, or a seq of JPoints.
The error occurs when creating a JShape and is thrown from jsony.nim proc parseObjectInner[T](s: string, i: var int, v: var T) = where it assigns v = v2 (line 390 in the version I have)
Here are some strange observations:
- If I simplify the
JValtype to just one int member, the problem goes away. - The problem comes back if I add any other member in JVal; it doesn't have to be a variant to fail
- Within
parseObjectInnerI canecho v2.typeofand getseq[JPoint]which is correct, and I canecho v2which displays the@[...]sequence, but if Iecho v2.lenthen compiler fails with type mismatch: v2 is ShapeKind. - This weirdness occurs even if JVal type has one int member and the program works overall.
- I have tried various versions of this, both with and without quotes, trying to parse my own seq[int] in another parsehook, etc., and this weird nil access always appears when the json becomes a real object like skLine, skPolyLine, etc. Just parsing a seq of JPoints seems to work.
Why can't I get this to work?
Thanks
import std/[json, strutils]
import jsony
type
VarKind = enum vkInt, vkFloat, vkString
JVal = object
case kind: VarKind
of vkInt: intVal: int
of vkFloat: floatVal: float
of vkString: strVal: string
JPoint = object of RootObj
x, y: JVal
ShapeKind = enum skLine, skPolyLine
JShape = object
case kind: ShapeKind
of skLine:
pt0: JPoint
pt1: JPoint
of skPolyLine:
pts: seq[JPoint]
proc parseHook(s: string, i: var int, val: var JVal) =
# Only parse ints for now to keep it simple
var x: int
parseHook(s, i, x)
val = JVal(kind: vkInt, intVal: x)
echo "created jval: ", val
proc parseHook(s: string, i: var int, val: var JPoint) =
# Parse (x, y)
echo "Parsing JPoint at index ", i
var x, y: JVal
eatChar(s, i, '"')
eatChar(s, i, '(')
parseHook(s, i, x)
eatChar(s, i, ',')
parseHook(s, i, y)
eatChar(s, i, ')')
eatChar(s, i, '"')
val = JPoint(x: x, y: y)
try:
# OK
echo "Doing JPoint"
echo """ "(1, 2)" """.fromJson(JPoint)
echo ""
# OK
echo "Doing seq of JPoints"
echo """ ["(1, 2)", "(3, 4)"] """.fromJson(seq[JPoint])
echo ""
# OK
echo "Doing JShape with line"
echo """{"kind": "skLine", "pt0": "(1, 2)", "pt1": "(3, 4)"}""".fromJson(JShape)
echo ""
# Error: SIGSEGV: Illegal storage access. (Attempt to read from nil?)
echo "doing JShape with polyline"
echo """{"kind": "skPolyLine", "pts": ["(1, 2)", "(3, 4)"]}""".fromJson(JShape)
echo ""
except Exception as e:
echo e.msg
echo e.getStackTrace()