mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 09:24:36 +00:00
249 lines
5.1 KiB
Nim
249 lines
5.1 KiB
Nim
discard """
|
||
file: "tjsonmacro.nim"
|
||
output: ""
|
||
"""
|
||
import json, strutils
|
||
|
||
when isMainModule:
|
||
# Tests inspired by own use case (with some additional tests).
|
||
# This should succeed.
|
||
type
|
||
Point[T] = object
|
||
x, y: T
|
||
|
||
ReplayEventKind* = enum
|
||
FoodAppeared, FoodEaten, DirectionChanged
|
||
|
||
ReplayEvent* = object
|
||
time*: float
|
||
case kind*: ReplayEventKind
|
||
of FoodAppeared, FoodEaten:
|
||
foodPos*: Point[float]
|
||
of DirectionChanged:
|
||
playerPos*: float
|
||
|
||
Replay* = ref object
|
||
events*: seq[ReplayEvent]
|
||
test: int
|
||
test2: string
|
||
test3: bool
|
||
testNil: string
|
||
|
||
var x = Replay(
|
||
events: @[
|
||
ReplayEvent(
|
||
time: 1.2345,
|
||
kind: FoodEaten,
|
||
foodPos: Point[float](x: 5.0, y: 1.0)
|
||
)
|
||
],
|
||
test: 18827361,
|
||
test2: "hello world",
|
||
test3: true,
|
||
testNil: nil
|
||
)
|
||
|
||
let node = %x
|
||
|
||
let y = to(node, Replay)
|
||
doAssert y.events[0].time == 1.2345
|
||
doAssert y.events[0].kind == FoodEaten
|
||
doAssert y.events[0].foodPos.x == 5.0
|
||
doAssert y.events[0].foodPos.y == 1.0
|
||
doAssert y.test == 18827361
|
||
doAssert y.test2 == "hello world"
|
||
doAssert y.test3
|
||
doAssert y.testNil.isNil
|
||
|
||
# Test for custom object variants (without an enum) and with an else branch.
|
||
block:
|
||
type
|
||
TestVariant = object
|
||
name: string
|
||
case age: uint8
|
||
of 2:
|
||
preSchool: string
|
||
of 8:
|
||
primarySchool: string
|
||
else:
|
||
other: int
|
||
|
||
var node = %{
|
||
"name": %"Nim",
|
||
"age": %8,
|
||
"primarySchool": %"Sandtown"
|
||
}
|
||
|
||
var result = to(node, TestVariant)
|
||
doAssert result.age == 8
|
||
doAssert result.name == "Nim"
|
||
doAssert result.primarySchool == "Sandtown"
|
||
|
||
node = %{
|
||
"name": %"⚔️Foo☢️",
|
||
"age": %25,
|
||
"other": %98
|
||
}
|
||
|
||
result = to(node, TestVariant)
|
||
doAssert result.name == node["name"].getStr()
|
||
doAssert result.age == node["age"].getInt().uint8
|
||
doAssert result.other == node["other"].getBiggestInt()
|
||
|
||
# TODO: Test object variant with set in of branch.
|
||
# TODO: Should we support heterogenous arrays?
|
||
|
||
# Tests that verify the error messages for invalid data.
|
||
block:
|
||
type
|
||
Person = object
|
||
name: string
|
||
age: int
|
||
|
||
var node = %{
|
||
"name": %"Dominik"
|
||
}
|
||
|
||
try:
|
||
discard to(node, Person)
|
||
doAssert false
|
||
except KeyError as exc:
|
||
doAssert("age" in exc.msg)
|
||
except:
|
||
doAssert false
|
||
|
||
node["age"] = %false
|
||
|
||
try:
|
||
discard to(node, Person)
|
||
doAssert false
|
||
except JsonKindError as exc:
|
||
doAssert("age" in exc.msg)
|
||
except:
|
||
doAssert false
|
||
|
||
type
|
||
PersonAge = enum
|
||
Fifteen, Sixteen
|
||
|
||
PersonCase = object
|
||
name: string
|
||
case age: PersonAge
|
||
of Fifteen:
|
||
discard
|
||
of Sixteen:
|
||
id: string
|
||
|
||
try:
|
||
discard to(node, PersonCase)
|
||
doAssert false
|
||
except JsonKindError as exc:
|
||
doAssert("age" in exc.msg)
|
||
except:
|
||
doAssert false
|
||
|
||
# Test the example in json module.
|
||
block:
|
||
let jsonNode = parseJson("""
|
||
{
|
||
"person": {
|
||
"name": "Nimmer",
|
||
"age": 21
|
||
},
|
||
"list": [1, 2, 3, 4]
|
||
}
|
||
""")
|
||
|
||
type
|
||
Person = object
|
||
name: string
|
||
age: int
|
||
|
||
Data1 = object # TODO: Codegen bug when changed to ``Data``.
|
||
person: Person
|
||
list: seq[int]
|
||
|
||
var data = to(jsonNode, Data1)
|
||
doAssert data.person.name == "Nimmer"
|
||
doAssert data.person.age == 21
|
||
doAssert data.list == @[1, 2, 3, 4]
|
||
|
||
# Test non-variant enum fields.
|
||
block:
|
||
type
|
||
EnumType = enum
|
||
Foo, Bar
|
||
|
||
TestEnum = object
|
||
field: EnumType
|
||
|
||
var node = %{
|
||
"field": %"Bar"
|
||
}
|
||
|
||
var result = to(node, TestEnum)
|
||
doAssert result.field == Bar
|
||
|
||
# Test ref type in field.
|
||
block:
|
||
var jsonNode = parseJson("""
|
||
{
|
||
"person": {
|
||
"name": "Nimmer",
|
||
"age": 21
|
||
},
|
||
"list": [1, 2, 3, 4]
|
||
}
|
||
""")
|
||
|
||
type
|
||
Person = ref object
|
||
name: string
|
||
age: int
|
||
|
||
Data = object
|
||
person: Person
|
||
list: seq[int]
|
||
|
||
var data = to(jsonNode, Data)
|
||
doAssert data.person.name == "Nimmer"
|
||
doAssert data.person.age == 21
|
||
doAssert data.list == @[1, 2, 3, 4]
|
||
|
||
jsonNode = parseJson("""
|
||
{
|
||
"person": null,
|
||
"list": [1, 2, 3, 4]
|
||
}
|
||
""")
|
||
data = to(jsonNode, Data)
|
||
doAssert data.person.isNil
|
||
|
||
block:
|
||
type
|
||
FooBar = object
|
||
field: float
|
||
|
||
let x = parseJson("""{ "field": 5}""")
|
||
let data = to(x, FooBar)
|
||
doAssert data.field == 5.0
|
||
|
||
block:
|
||
type
|
||
BirdColor = object
|
||
name: string
|
||
rgb: array[3, float]
|
||
|
||
type
|
||
Bird = object
|
||
age: int
|
||
height: float
|
||
name: string
|
||
colors: array[2, BirdColor]
|
||
|
||
var red = BirdColor(name: "red", rgb: [1.0, 0.0, 0.0])
|
||
var blue = Birdcolor(name: "blue", rgb: [0.0, 0.0, 1.0])
|
||
var b = Bird(age: 3, height: 1.734, name: "bardo", colors: [red, blue])
|
||
let jnode = %b
|
||
let data = jnode.to(Bird)
|
||
doAssert data == b |