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 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:
Why can't I get this to work? Thanks
(will post this in jsony github issues too)
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()Weird. It works correctly when changing the order of ShapeKind enum values:
ShapeKind = enum skPolyLine, skLine
Looks like this is some bug in jsony.
The bug is with ORC/ARC and the handling of case objects and RootObj.
I slowly removed parts from your example while it continued to crash:
type
JPoint = object of RootObj
ShapeKind = enum a, b
JShape = object
case kind: ShapeKind
of a:
x: JPoint
of b:
y: seq[string]
var v: JShape
{.cast(uncheckedAssign).}:
v.kind = b
This only happens with --mm:orc or --mm:arc, but not with --mm:refc.
This also happens with the stdlib JSON parser:
import json
type
JPoint = object of RootObj
ShapeKind = enum a, b
JShape = object
case kind: ShapeKind
of a:
x: JPoint
of b:
y: seq[string]
discard """{"kind": "b", "y": [""]}""".parseJson.to(JShape)
It's odd to have of RootObj that is not a ref attached to a case object.