# json-serialization # Copyright (c) 2024 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * MIT license ([LICENSE-MIT](LICENSE-MIT)) # at your option. # This file may not be copied, modified, or distributed except according to # those terms. import unittest2, ../json_serialization/stew/results, ../json_serialization/std/options, ../json_serialization type ObjectWithOptionalFields = object a: Opt[int] b: Option[string] c: int OWOF = object a: Opt[int] b: Option[string] c: int createJsonFlavor YourJson, omitOptionalFields = false createJsonFlavor MyJson, omitOptionalFields = true ObjectWithOptionalFields.useDefaultSerializationIn YourJson ObjectWithOptionalFields.useDefaultSerializationIn MyJson type FruitX = enum BananaX = "BaNaNa" AppleX = "ApplE" GrapeX = "VVV" Drawer = enum One Two FruitX.configureJsonSerialization(EnumAsString) Json.configureJsonSerialization(Drawer, EnumAsNumber) MyJson.configureJsonSerialization(Drawer, EnumAsString) proc writeValue*(w: var JsonWriter, val: OWOF) {.gcsafe, raises: [IOError].} = w.writeObject(OWOF): w.writeField("a", val.a) w.writeField("b", val.b) w.writeField("c", val.c) suite "Test writer": test "stdlib option top level some YourJson": var val = some(123) let json = YourJson.encode(val) check json == "123" test "stdlib option top level none YourJson": var val = none(int) let json = YourJson.encode(val) check json == "null" test "stdlib option top level some MyJson": var val = some(123) let json = MyJson.encode(val) check json == "123" test "stdlib option top level none MyJson": var val = none(int) let json = MyJson.encode(val) check json == "null" test "results option top level some YourJson": var val = Opt.some(123) let json = YourJson.encode(val) check json == "123" test "results option top level none YourJson": var val = Opt.none(int) let json = YourJson.encode(val) check json == "null" test "results option top level some MyJson": var val = Opt.some(123) let json = MyJson.encode(val) check json == "123" test "results option top level none MyJson": var val = Opt.none(int) let json = MyJson.encode(val) check json == "null" test "stdlib option array some YourJson": var val = [some(123), some(345)] let json = YourJson.encode(val) check json == "[123,345]" test "stdlib option array none YourJson": var val = [some(123), none(int), some(777)] let json = YourJson.encode(val) check json == "[123,null,777]" test "stdlib option array some MyJson": var val = [some(123), some(345)] let json = MyJson.encode(val) check json == "[123,345]" test "stdlib option array none MyJson": var val = [some(123), none(int), some(777)] let json = MyJson.encode(val) check json == "[123,null,777]" test "results option array some YourJson": var val = [Opt.some(123), Opt.some(345)] let json = YourJson.encode(val) check json == "[123,345]" test "results option array none YourJson": var val = [Opt.some(123), Opt.none(int), Opt.some(777)] let json = YourJson.encode(val) check json == "[123,null,777]" test "results option array some MyJson": var val = [Opt.some(123), Opt.some(345)] let json = MyJson.encode(val) check json == "[123,345]" test "results option array none MyJson": var val = [Opt.some(123), Opt.none(int), Opt.some(777)] let json = MyJson.encode(val) check json == "[123,null,777]" test "object with optional fields": let x = ObjectWithOptionalFields( a: Opt.some(123), b: some("nano"), c: 456, ) let y = ObjectWithOptionalFields( a: Opt.none(int), b: none(string), c: 999, ) let u = YourJson.encode(x) check u.string == """{"a":123,"b":"nano","c":456}""" let v = YourJson.encode(y) check v.string == """{"a":null,"b":null,"c":999}""" let xx = MyJson.encode(x) check xx.string == """{"a":123,"b":"nano","c":456}""" let yy = MyJson.encode(y) check yy.string == """{"c":999}""" test "writeField with object with optional fields": let x = OWOF( a: Opt.some(123), b: some("nano"), c: 456, ) let y = OWOF( a: Opt.none(int), b: none(string), c: 999, ) let xx = MyJson.encode(x) check xx.string == """{"a":123,"b":"nano","c":456}""" let yy = MyJson.encode(y) check yy.string == """{"c":999}""" let uu = YourJson.encode(x) check uu.string == """{"a":123,"b":"nano","c":456}""" let vv = YourJson.encode(y) check vv.string == """{"a":null,"b":null,"c":999}""" test "Enum value representation primitives": when DefaultFlavor.flavorEnumRep() == EnumAsString: check true elif DefaultFlavor.flavorEnumRep() == EnumAsNumber: check false elif DefaultFlavor.flavorEnumRep() == EnumAsStringifiedNumber: check false DefaultFlavor.flavorEnumRep(EnumAsNumber) when DefaultFlavor.flavorEnumRep() == EnumAsString: check false elif DefaultFlavor.flavorEnumRep() == EnumAsNumber: check true elif DefaultFlavor.flavorEnumRep() == EnumAsStringifiedNumber: check false DefaultFlavor.flavorEnumRep(EnumAsStringifiedNumber) when DefaultFlavor.flavorEnumRep() == EnumAsString: check false elif DefaultFlavor.flavorEnumRep() == EnumAsNumber: check false elif DefaultFlavor.flavorEnumRep() == EnumAsStringifiedNumber: check true test "Enum value representation of DefaultFlavor": type ExoticFruits = enum DragonFruit SnakeFruit StarFruit DefaultFlavor.flavorEnumRep(EnumAsNumber) let u = Json.encode(DragonFruit) check u == "0" DefaultFlavor.flavorEnumRep(EnumAsString) let v = Json.encode(SnakeFruit) check v == "\"SnakeFruit\"" DefaultFlavor.flavorEnumRep(EnumAsStringifiedNumber) let w = Json.encode(StarFruit) check w == "\"2\"" test "EnumAsString of DefaultFlavor/Json": type Fruit = enum Banana = "BaNaNa" Apple = "ApplE" JackFruit = "VVV" ObjectWithEnumField = object fruit: Fruit Json.flavorEnumRep(EnumAsString) let u = Json.encode(Banana) check u == "\"BaNaNa\"" let v = Json.encode(Apple) check v == "\"ApplE\"" let w = Json.encode(JackFruit) check w == "\"VVV\"" Json.flavorEnumRep(EnumAsStringifiedNumber) let x = Json.encode(JackFruit) check x == "\"2\"" Json.flavorEnumRep(EnumAsNumber) let z = Json.encode(Banana) check z == "0" let obj = ObjectWithEnumField(fruit: Banana) let zz = Json.encode(obj) check zz == """{"fruit":0}""" test "Individual enum configuration": Json.flavorEnumRep(EnumAsNumber) # Although the flavor config is EnumAsNumber # FruitX is configured as EnumAsAstring let z = Json.encode(BananaX) check z == "\"BaNaNa\"" # configuration: Json.configureJsonSerialization(Drawer, EnumAsNumber) let u = Json.encode(Two) check u == "1" # configuration: MyJson.configureJsonSerialization(Drawer, EnumAsString) let v = MyJson.encode(One) check v == "\"One\""