-
-
Save planetis-m/00eb3ca829397e47417a4eb2f8036d60 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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