我正在使用 Nim 开发一个小型 Web 服务,需要使用 JSON 响应请求。我使用 Jester 模块实现这个服务。我希望能够使用 Nim 的基础库中的 JSON 模块构造具有字段和值的某种对象,然后将其转换为 JSON 字符串。但是,如何做到呢?或者在 Nim 中构建 JSON 是否有更好的方法?
marshal模块包含一个通用的对象到JSON序列化算法,可适用于任何类型(目前使用运行时类型内省)。
import marshal
type
Person = object
age: int
name: string
var p = Person(age: 38, name: "Torbjørn")
echo($$p)
输出结果将是:
{"age": 38, "name": "Torbj\u00F8rn"}
JsonNode
对象,这些对象是对象变体。它们可以通过像newJObject()这样的单独过程构建,然后填充fields
序列。另一种更快的方法是使用%()过程,它接受一个元组序列,其中一个值是带有json字段的字符串,另一个值是单个的JsonNode
对象。
以下是两种方式的示例:
import json
type
Person = object ## Our generic person record.
age: int ## The age of the person.
name: string ## The name of the person.
proc `%`(p: Person): JsonNode =
## Quick wrapper around the generic JObject constructor.
result = %[("age", %p.age), ("name", %p.name)]
proc myCustomJson(p: Person): JsonNode =
## Custom method where we replicate manual construction.
result = newJObject()
# Initialize empty sequence with expected field tuples.
var s: seq[tuple[key: string, val: JsonNode]] = @[]
# Add the integer field tuple to the sequence of values.
s.add(("age", newJInt(p.age)))
# Add the string field tuple to the sequence of values.
s.add(("name", newJString(p.name)))
result.fields = s
proc test() =
# Tests making some jsons.
var p: Person
p.age = 24
p.name = "Minah"
echo(%p) # { "age": 24, "name": "Minah"}
p.age = 33
p.name = "Sojin"
echo(%p) # { "age": 33, "name": "Sojin"}
p.age = 40
p.name = "Britney"
echo p.myCustomJson # { "age": 40, "name": "Britney"}
when isMainModule: test()
对于其他人在这个讨论中找到了基于 marshal
的答案。请改用以下方法:
import json
type
Person = object
age: int
name: string
var p = Person(age: 38, name: "Torbjørn")
echo(%p)
marshal
来完成此目的,它相当于 Python 中的 pickle
模块,可能会生成包含额外数据的 JSON,这可能不是您想要的。此外,现在它只是偶然生成 JSON,未来可能会选择不同的格式。echo
隐式地在其参数上调用 $
(请参阅 echo
的文档)。$
是 Nim 的“toString”函数。因此,只需为您的数据类型实现 $
,即可打印其字符串表示形式。%
返回一个 JsonNode
,并且 JsonNode
已经实现了 $
,因此 echo %p
(或 echo $ %p
)可以工作。非常简单明了。 “假设如果您的 Person 类型具有不是字符串或整数的属性,则需要进行更多的工作”-当然...json 模块的实现者已经完成了这项工作。(而 int
并不特殊-int
的 $
由 Nim 库提供。) - Jim Balter%p
时,会出现编译错误,这与echo
无关。echo %p
实际上是stdout.writeln $(%p)
。如果没有在作用域中定义一个接受p
类型参数的%
,那么当然会出错。再次强调,这一切都非常简单,并不特定于json
、%
、echo
等。 - Jim Balter请执行以下步骤:
import json
var jsonResponse = %*
{"data": [{ "id": 35,
"type": "car",
"attributes": {"color":"red"} }]}
var body = ""
toUgly(body, jsonResponse)
echo body
marshal
模块相当于Python中的pickle
,它使用JSON作为序列化格式纯属巧合,不要使用它来将对象序列化为JSON。特别是现在因为json
模块支持了几乎相同的功能,所以更不应该这样做:https://play.nim-lang.org/#ix=2uPe - dom96