mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-09 14:32:53 +00:00
fix jsonutils with generic sandwiches, don't use strformat (#24560)
fixes #24559 The strformat macros have the problem that they don't capture symbols, so don't use them in the generic `fromJson` proc here. Also `fromJson` refers to `jsonTo` before it is declared which doesn't capture it, so it's now forward declared.
This commit is contained in:
@@ -16,7 +16,7 @@ runnableExamples:
|
||||
assert 0.0.toJson.kind == JFloat
|
||||
assert Inf.toJson.kind == JString
|
||||
|
||||
import std/[json, strutils, tables, sets, strtabs, options, strformat]
|
||||
import std/[json, strutils, tables, sets, strtabs, options]
|
||||
|
||||
#[
|
||||
Future directions:
|
||||
@@ -205,6 +205,8 @@ proc discKeysMatch[T](obj: T, json: JsonNode, keys: static seq[string]): bool =
|
||||
result = true
|
||||
discKeysMatchBodyGen(obj, json, keys)
|
||||
|
||||
proc jsonTo*(b: JsonNode, T: typedesc, opt = Joptions()): T
|
||||
|
||||
proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
|
||||
## inplace version of `jsonTo`
|
||||
#[
|
||||
@@ -218,7 +220,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
|
||||
case b.kind
|
||||
of JInt: a = T(b.getBiggestInt())
|
||||
of JString: a = parseEnum[T](b.getStr())
|
||||
else: checkJson false, fmt"Expecting int/string for {$T} got {b.pretty()}"
|
||||
else: checkJson false, "Expecting int/string for " & $T & " got " & b.pretty()
|
||||
elif T is uint|uint64: a = T(to(b, uint64))
|
||||
elif T is Ordinal: a = cast[T](to(b, int))
|
||||
elif T is pointer: a = cast[pointer](to(b, int))
|
||||
@@ -228,7 +230,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
|
||||
case b.kind
|
||||
of JNull: a = nil
|
||||
of JString: a = b.str
|
||||
else: checkJson false, fmt"Expecting null/string for {$T} got {b.pretty()}"
|
||||
else: checkJson false, "Expecting null/string for " & $T & " got " & b.pretty()
|
||||
elif T is JsonNode: a = b
|
||||
elif T is ref | ptr:
|
||||
if b.kind == JNull: a = nil
|
||||
@@ -236,7 +238,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
|
||||
a = T()
|
||||
fromJson(a[], b, opt)
|
||||
elif T is array:
|
||||
checkJson a.len == b.len, fmt"Json array size doesn't match for {$T}"
|
||||
checkJson a.len == b.len, "Json array size doesn't match for " & $T
|
||||
var i = 0
|
||||
for ai in mitems(a):
|
||||
fromJson(ai, b[i], opt)
|
||||
@@ -282,7 +284,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
|
||||
for val in fields(a):
|
||||
tupleSize.inc
|
||||
|
||||
checkJson b.len == tupleSize, fmt"Json doesn't match expected length of {tupleSize}, got {b.pretty()}"
|
||||
checkJson b.len == tupleSize, "Json doesn't match expected length of " & $tupleSize & ", got " & b.pretty()
|
||||
var i = 0
|
||||
for val in fields(a):
|
||||
fromJson(val, b[i], opt)
|
||||
|
||||
11
tests/stdlib/mjsonutilssandwich.nim
Normal file
11
tests/stdlib/mjsonutilssandwich.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
import std/[json, jsonutils]
|
||||
|
||||
type
|
||||
Kind* = enum kind1
|
||||
Foo* = ref object
|
||||
bleh: string
|
||||
case kind*: Kind # Remove these lines and everything works 🤡
|
||||
of kind1: discard # Remove these lines and everything works 🤡
|
||||
|
||||
proc unserialize*[T](s: string) =
|
||||
discard jsonTo(parseJson(s), T)
|
||||
10
tests/stdlib/tjsonutilssandwich.nim
Normal file
10
tests/stdlib/tjsonutilssandwich.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
discard """
|
||||
action: compile
|
||||
"""
|
||||
|
||||
# issue #24559
|
||||
|
||||
import mjsonutilssandwich
|
||||
# import std/[json, jsonutils] # Add this line and everything works 🤡
|
||||
|
||||
unserialize[Foo]("{}")
|
||||
Reference in New Issue
Block a user