Skip to content

Instantly share code, notes, and snippets.

@planetis-m
Created June 9, 2021 20:12
Show Gist options
  • Save planetis-m/00eb3ca829397e47417a4eb2f8036d60 to your computer and use it in GitHub Desktop.
Save planetis-m/00eb3ca829397e47417a4eb2f8036d60 to your computer and use it in GitHub Desktop.
import eminim, std/[parsejson, streams]
type
Fruit = enum
Banana, Apple
Bar = object
shared: int
case kind: Fruit
of Banana:
bad: float
banana: int
of Apple: apple: string
proc initFromJson(dst: var Bar, p: var JsonParser) =
var
onceShared, onceKind, onceBad, onceBanana, onceApple = false
eat(p, tkCurlyLe)
while p.tok != tkCurlyRi:
if p.tok != tkString:
raiseParseErr(p, "string literal as key")
case p.a
of "shared":
discard getTok(p)
eat(p, tkColon)
if not onceShared:
onceShared = true
initFromJson(dst.shared, p)
else:
when defined(emiDuplicateKey): skipJson(p)
else: raiseParseErr(p, "duplicate object field")
of "kind":
discard getTok(p)
eat(p, tkColon)
var kindTmp: Fruit
if not onceKind:
onceKind = true
initFromJson(kindTmp, p)
else:
when defined(emiDuplicateKey): skipJson(p)
else: raiseParseErr(p, "duplicate object field")
if dst.kind != kindTmp:
case dst.kind
of Banana:
if onceBad or onceBanana:
when not defined(emiLenient): raiseParseErr(p, "valid object field")
if onceShared:
var tmpShared: int
if onceShared: tmpShared = dst.shared
dst = (typeof dst)(kind: kindTmp, shared: tmpShared)
of Apple:
if onceApple:
when not defined(emiLenient): raiseParseErr(p, "valid object field")
var tmpShared: int
if onceShared: tmpShared = dst.shared
dst = (typeof dst)(kind: kindTmp, shared: tmpShared)
of "bad":
if dst.kind != Banana:
if onceApple:
when not defined(emiLenient): raiseParseErr(p, "valid object field")
var tmpShared: int
if onceShared: tmpShared = dst.shared
dst = (typeof dst)(kind: Banana, shared: tmpShared)
discard getTok(p)
eat(p, tkColon)
if not onceBad:
onceBad = true
initFromJson(dst.bad, p)
else:
when defined(emiDuplicateKey): skipJson(p)
else: raiseParseErr(p, "duplicate object field")
of "banana":
if dst.kind != Banana:
if onceApple:
when not defined(emiLenient): raiseParseErr(p, "valid object field")
var tmpShared: int
if onceShared: tmpShared = dst.shared
dst = (typeof dst)(kind: Banana, shared: tmpShared)
discard getTok(p)
eat(p, tkColon)
if not onceBanana:
onceBanana = true
initFromJson(dst.banana, p)
else:
when defined(emiDuplicateKey): skipJson(p)
else: raiseParseErr(p, "duplicate object field")
of "apple":
if dst.kind != Apple:
if onceBad or onceBanana:
when not defined(emiLenient): raiseParseErr(p, "valid object field")
var tmpShared: int
if onceShared: tmpShared = dst.shared
dst = (typeof dst)(kind: Apple, shared: tmpShared)
discard getTok(p)
eat(p, tkColon)
if not onceApple:
onceApple = true
initFromJson(dst.apple, p)
else:
when defined(emiDuplicateKey): skipJson(p)
else: raiseParseErr(p, "duplicate object field")
else:
when defined(emiLenient): skipJson(p)
else: raiseParseErr(p, "valid object field")
if p.tok != tkComma:
break
discard getTok(p)
eat(p, tkCurlyRi)
let s = newStringStream("""[{"shared":1,"kind":"Apple","apple":"world"},{"bad":1.0,"kind":"Banana","shared":2}]""")
echo s.jsonTo(seq[Bar])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment