You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp使用CL-JSON将alist转JSON报错的原因与解决方法

问题原因

报错的核心原因是传入json:encode-json-alist-to-string的参数根本不是预期的alist结构:

  • 你定义的用户输入字符串最前面带了Lisp的引用语法糖单引号',read-from-string读取这个字符串时,会把单引号解析为quote符号,最终读出来的结果是(quote (("name" . "John")))——这是一个首元素为符号QUOTE、第二个元素才是目标alist的列表,而非alist本身。
  • 你直接在REPL里手写'(("name" . "Pedro"))能正常运行,是因为Lisp求值器会自动处理quote表达式,返回引号包裹的实际alist值;但read-from-string只做语法读取、不做求值,所以你拿到的返回值是未求值的quote表达式,自然不符合CL-JSON对alist参数的类型要求。

你可以自行验证读入结果的结构:

CL-USER> (car (read-from-string input-from-user))
QUOTE
解决方案

根据场景选以下任意一种方案即可:

  • 方案一(最推荐,无安全风险):从输入源头去掉前置单引号,让read-from-string直接读出alist结构
    ;; 输入字符串去掉最开头的'
    CL-USER> (defvar input-from-user "((\"name\" . \"John\"))")
    INPUT-FROM-USER
    CL-USER> (json:encode-json-alist-to-string (read-from-string input-from-user))
    "{\"name\":\"John\"}"
    
  • 方案二(适合无法修改用户输入规则的场景,无安全风险):读取后手动取出quote包裹的实际alist值,也就是读入结果的第二个元素,代码做兼容判断可以同时支持带引号和不带引号的输入
    CL-USER> (defvar input-from-user "'((\"name\" . \"John\"))")
    INPUT-FROM-USER
    CL-USER> (let ((parsed (read-from-string input-from-user)))
               (json:encode-json-alist-to-string
                (if (eq (car parsed) 'quote)
                    (cadr parsed)
                    parsed)))
    "{\"name\":\"John\"}"
    
  • 方案三(仅适合完全可信的输入场景,有安全风险):对读入的结果直接求值

    注意:如果用户输入不可信,绝对不要用这个方案,恶意构造的输入会被直接执行,带来严重安全问题。

    CL-USER> (json:encode-json-alist-to-string (eval (read-from-string input-from-user)))
    "{\"name\":\"John\"}"
    

内容的提问来源于stack exchange,提问作者Pedro Delfino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 00:18:20