diff --git a/src/preserves.nim b/src/preserves.nim index d9a52a8..0c97817 100644 --- a/src/preserves.nim +++ b/src/preserves.nim @@ -4,8 +4,7 @@ import bigints import std/[base64, endians, hashes, options, sets, streams, strutils, tables, typetraits] -import json except `%`, `%*` - +from std/json import escapeJson, escapeJsonUnquoted from std/macros import hasCustomPragma, getCustomPragmaVal type @@ -561,73 +560,6 @@ proc toPreserveHook*[A,B](table: Table[A,B]|TableRef[A,B]): Preserve = result = Preserve(kind: pkDictionary, dict: initTable[Preserve, Preserve](table.len)) for k, v in table.pairs: result.dict[toPreserve k] = toPreserve v -proc toPreserveHook*(js: JsonNode): Preserve = - case js.kind - of JString: - result = Preserve(kind: pkString, string: js.str) - of JInt: - result = Preserve(kind: pkSignedInteger, int: js.num) - of JFloat: - result = Preserve(kind: pkDouble, double: js.fnum) - of JBool: - result = case js.bval - of false: symbol"false" - of true: symbol"true" - of JNull: - result = symbol"null" - of JObject: - result = Preserve(kind: pkDictionary) - for key, val in js.fields.pairs: - result.dict[Preserve(kind: pkString, string: key)] = toPreserveHook(val) - of JArray: - result = Preserve(kind: pkSequence, - sequence: newSeq[Preserve](js.elems.len)) - for i, e in js.elems: - result.sequence[i] = toPreserveHook(e) - -proc toJsonHook*(prs: Preserve): JsonNode = - case prs.kind: - of pkBoolean: - result = newJBool(prs.bool) - of pkFloat: - result = newJFloat(prs.float) - of pkDouble: - result = newJFloat(prs.double) - of pkSignedInteger: - result = newJInt(prs.int) - of pkBigInteger: - raise newException(ValueError, "cannot convert big integer to JSON") - of pkString: - result = newJString(prs.string) - of pkByteString: - raise newException(ValueError, "cannot convert bytes to JSON") - of pkSymbol: - case prs.symbol - of "false": - result = newJBool(false) - of "true": - result = newJBool(true) - of "null": - result = newJNull() - else: - raise newException(ValueError, "cannot convert symbol to JSON") - of pkRecord: - raise newException(ValueError, "cannot convert record to JSON") - of pkSequence: - result = newJArray() - for val in prs.sequence: - result.add(toJsonHook(val)) - of pkSet: - raise newException(ValueError, "cannot convert set to JSON") - of pkDictionary: - result = newJObject() - for (key, val) in prs.dict.pairs: - if key.kind != pkString: - raise newException(ValueError, "cannot convert non-string dictionary key to JSON") - result[key.string] = toJsonHook(val) - of pkEmbedded: - raise newException(ValueError, "cannot convert embedded value to JSON") - proc fromPreserve*[T](v: var T; prs: Preserve): bool = ## Inplace version of `preserveTo`. ## Partial matches on compond values may leave artifacts in ``v``. diff --git a/src/preserves/jsonhooks.nim b/src/preserves/jsonhooks.nim new file mode 100644 index 0000000..462690a --- /dev/null +++ b/src/preserves/jsonhooks.nim @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: 2021 ☭ Emery Hemingway +# SPDX-License-Identifier: ISC + +import std/[json, tables] +import preserves + +proc toPreserveHook*(js: JsonNode): Preserve = + case js.kind + of JString: + result = Preserve(kind: pkString, string: js.str) + of JInt: + result = Preserve(kind: pkSignedInteger, int: js.num) + of JFloat: + result = Preserve(kind: pkDouble, double: js.fnum) + of JBool: + result = case js.bval + of false: symbol"false" + of true: symbol"true" + of JNull: + result = symbol"null" + of JObject: + result = Preserve(kind: pkDictionary) + for key, val in js.fields.pairs: + result.dict[Preserve(kind: pkString, string: key)] = toPreserveHook(val) + of JArray: + result = Preserve(kind: pkSequence, + sequence: newSeq[Preserve](js.elems.len)) + for i, e in js.elems: + result.sequence[i] = toPreserveHook(e) + +proc toJsonHook*(prs: Preserve): JsonNode = + case prs.kind: + of pkBoolean: + result = newJBool(prs.bool) + of pkFloat: + result = newJFloat(prs.float) + of pkDouble: + result = newJFloat(prs.double) + of pkSignedInteger: + result = newJInt(prs.int) + of pkBigInteger: + raise newException(ValueError, "cannot convert big integer to JSON") + of pkString: + result = newJString(prs.string) + of pkByteString: + raise newException(ValueError, "cannot convert bytes to JSON") + of pkSymbol: + case prs.symbol + of "false": + result = newJBool(false) + of "true": + result = newJBool(true) + of "null": + result = newJNull() + else: + raise newException(ValueError, "cannot convert symbol to JSON") + of pkRecord: + raise newException(ValueError, "cannot convert record to JSON") + of pkSequence: + result = newJArray() + for val in prs.sequence: + result.add(toJsonHook(val)) + of pkSet: + raise newException(ValueError, "cannot convert set to JSON") + of pkDictionary: + result = newJObject() + for (key, val) in prs.dict.pairs: + if key.kind != pkString: + raise newException(ValueError, "cannot convert non-string dictionary key to JSON") + result[key.string] = toJsonHook(val) + of pkEmbedded: + raise newException(ValueError, "cannot convert embedded value to JSON") diff --git a/tests/test_rfc8259.nim b/tests/test_rfc8259.nim index 1696633..2eabe7e 100644 --- a/tests/test_rfc8259.nim +++ b/tests/test_rfc8259.nim @@ -1,6 +1,7 @@ +# SPDX-FileCopyrightText: 2021 ☭ Emery Hemingway # SPDX-License-Identifier: ISC -import preserves +import preserves, preserves/jsonhooks import std/[json,jsonutils,streams, unittest] let testVectors = [