首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用CLOS库将json-string转换为CLOS对象?

如何使用CLOS库将json-string转换为CLOS对象?
EN

Stack Overflow用户
提问于 2019-03-06 05:00:05
回答 1查看 289关注 0票数 2

如果有一个类和一个json:

代码语言:javascript
复制
(defclass foo ()
    ((bar :initarg :bar)))

(defvar *input* "\{ \"bar\" : 3 }")

如何使用cl库将*input*转换为foo的实例?

我想应该是:

代码语言:javascript
复制
(with-decoder-simple-clos-semantics
    (let ((*prototype-name* 'foo))
      (decode-json-from-string *input*)))

但它产生了:

代码语言:javascript
复制
Invalid SB-MOP:SLOT-DEFINITION initialization: the
initialization argument :NAME was constant: :BAR.
   [Condition of type SB-PCL::SLOTD-INITIALIZATION-ERROR]

我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-06 08:52:28

导致此错误的原因是cl-json:*json-symbols-package*被绑定到KEYWORD包:当JSON键被转换为符号时,它们变成了关键字,显然它们作为插槽名无效。

流体物体

以下工作:

代码语言:javascript
复制
(let ((json:*json-symbols-package* (find-package :cl-user)))
  (json:with-decoder-simple-clos-semantics
    (json:decode-json-from-string "{ \"bar\" : 3 }")))

(注:双引号前只需反斜杠)

你得到了一个FLUID-OBJECT

JSON数据中的原型密钥

现在,您还可以定义自己的类:

代码语言:javascript
复制
(in-package :cl-user)
(defclass foo ()
  ((bar :initarg :bar)))

然后,JSON需要有一个"prototype"键:

代码语言:javascript
复制
 (let ((json:*json-symbols-package* (find-package :cl-user)))
   (json:with-decoder-simple-clos-semantics
     (json:decode-json-from-string
      "{ \"bar\" : 3 , 
         \"prototype\" : { \"lispClass\" : \"foo\", 
                           \"lispPackage\" : \"cl-user\"  }}")))

上面的内容返回FOO的一个实例。

通过重新绑定"prototype",可以使用与*prototype-name*不同的密钥。

强制使用默认原型(hack)

在不更改现有库代码的情况下,您可以对其进行黑客攻击,以更改解码步骤的行为。代码是围绕特殊变量组织的,这些变量在解析的各个点被用作回调,所以需要用自己的函数包装预期的函数:

代码语言:javascript
复制
(defun wrap-for-class (class &optional (fn json::*end-of-object-handler*))
  (let ((prototype (make-instance 'json::prototype :lisp-class class)))
    (lambda ()
      ;; dynamically rebind *prototype* right around calling fn
      (let ((json::*prototype* prototype))
        (funcall fn)))))

上面的代码为给定的类(符号)创建一个原型对象,捕获*end-of-object-handler*的当前绑定,并返回一个闭包,当调用该闭包时,将*prototype*绑定到关闭的原型实例。

然后,你这样称呼它:

代码语言:javascript
复制
(let ((json:*json-symbols-package* *package*))
  (json:with-decoder-simple-clos-semantics
    (let ((json::*end-of-object-handler* (wrap-for-class 'foo)))
      (json:decode-json-from-string
       "{ \"bar\" : 3 }"))))

并且您有一个FOO实例。

递归

请注意,如果您按照以下方式定义foo

代码语言:javascript
复制
(defclass foo ()
  ((bar :initarg :bar :accessor bar)
   (foo :initarg :foo :accessor foo)))

然后,黑客还将嵌套的JSON对象读入FOO:

代码语言:javascript
复制
(let ((json:*json-symbols-package* *package*))
  (json:with-decoder-simple-clos-semantics
    (let ((json::*end-of-object-handler* (wrap-for-class 'foo)))
      (json:decode-json-from-string
       "{ \"bar\" : 3, \"foo\" : { \"bar\" : 10} }"))))

=> #<FOO {1007A70E23}>

> (describe *)
#<FOO {1007A70E23}>
  [standard-object]

Slots with :INSTANCE allocation:
  BAR                            = 3
  FOO                            = #<FOO {1007A70D53}>

> (describe (foo **))
#<FOO {1007A70D53}>
  [standard-object]

 Slots with :INSTANCE allocation:
  BAR                            = 10
  FOO                            = #<unbound slot>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55015871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档