【问题标题】:Destructuring macro for ST-JSON JSO objectST-JSON JSO 对象的解构宏
【发布时间】:2014-04-24 10:57:45
【问题描述】:

我还有一个关于在 Common Lisp 中解码 JSON 的问题。我选择ST-JSON 作为我的工具。我能够得到一个包含 JSON 数据的JSO 对象,并使用st-json:getjso 访问所有字段。我想编写一个原则上类似于destructuring-bind 的宏,它可以为以 JSON 字段命名的变量提供本地绑定(从那时起,我开始怀疑这是否是一个好主意,但这是一个不同的问题)。我想出了以下几点:

(defmacro destructure-jso (jso &body body)
  (let (keys values)
    (st-json:mapjso #'(lambda (key value)
            (push key keys)
            (push value values))
            jso)
    `(destructuring-bind ,keys ,values
       ,@body)))

但是当我尝试在JSO 对象上使用它时,我收到错误The value PARAMS is not of the expected type STRUCTURE. 其中PARAMS 是对象。谁可以给我解释一下这个?

谢谢。

【问题讨论】:

    标签: json macros lisp common-lisp ccl


    【解决方案1】:

    显然,您正在像这样使用destructure-jso

    (let ((params (st-json:read-json-from-string "{\"foo\":42,\"bar\":\"baz\"}")))
      (destructure-jso params
        (list foo bar)))
    

    然而,destructure-jso,作为一个宏,在宏扩展时被处理,远在 JSON 被解析之前。 params 作为符号传递给您的宏,而不被评估;即使尝试了它的求值,它也不会被绑定。

    所以,如果你想写一个destructure-jso,你需要宏扩展时的键列表。您可以以正常方式传递列表:

    > (defmacro destructure-jso-2 (vars json &body body)
        `(let ,(mapcar #'(lambda (var)
                           (list var `(getjso ,(string-downcase (symbol-name var)) ,json)))
                       vars)
           ,@body))
    DESTRUCTURE-JSO-2
    
    > (let ((params (st-json:read-json-from-string "{\"foo\":42,\"bar\":\"baz\"}")))
        (destructure-jso-2 (foo bar)
        params
      (list foo bar)))
    (42 "baz")
    

    或者,如果您愿意,可以使用“模板”JSON 来创建映射:

    > (defmacro destructure-jso-3 (template json &body body)
        (let (bindings)
          (st-json:mapjso #'(lambda (key val)
                              (declare (ignore val))
                              (push (list (intern (string-upcase key)) `(getjso ,key ,json))
                                    bindings))
                          (st-json:read-json-from-string template))
          `(let ,bindings
             ,@body)))
    DESTRUCTURE-JSO-3
    
    > (let ((params (st-json:read-json-from-string "{\"foo\":42,\"bar\":\"baz\"}")))
        (destructure-jso-3 "{\"foo\":null,\"bar\":null}"
            params
          (list foo bar)))
    (42 "baz")
    

    这里,变量绑定来自第一个(模板)JSON,值来自第二个。模板 JSON 在宏扩展时解析,每次执行代码时都会解析 params JSON。

    这两种方法对你是否有用,我不知道。

    【讨论】:

    • 谢谢@jlahd。第一种方法 (destructure-jso-2) 与我想要的更相似,也更容易避免隐藏中间符号等问题。
    猜你喜欢
    • 2021-11-15
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多