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

求助:Lisp中JSON文件读写函数的实现与问题排查

问题分析与修复方案

早上好!让我们一步步搞定你在Lisp中实现JSON读写函数遇到的问题~

一、json-load函数的问题与修复

先看你写的两个版本的json-load,核心问题集中在变量作用域错误和参数传递逻辑错误:

  • 初始版本里,file-contents是定义在with-open-file的局部let块内,外部的(json-parse (file-contents))根本访问不到这个变量,而且这里把变量当成函数调用,语法本身就错了。
  • 修改后的版本里,你调用file-get-contents拿到了文件内容,但没有把这个内容传给json-parse,反而把文件名传了进去——json-parse需要的是JSON格式的字符串,不是文件名,这才会导致“undefined JSON object”的错误。

另外,file-get-contents里的with-open-file最好明确指定输入方向和不存在报错的行为,避免依赖默认值带来的意外。

修复后的json-load函数如下:

(defun json-load (filename)
  (let ((file-contents (file-get-contents filename)))
    (json-parse file-contents)))

(defun file-get-contents (filename)
  (with-open-file (stream filename
                          :direction :input
                          :if-does-not-exist :error)
    (let ((contents (make-string (file-length stream))))
      (read-sequence contents stream)
      contents)))

这个版本的逻辑是:先通过file-get-contents读取文件的完整内容字符串,再把这个字符串传给json-parse解析,完全符合你“先读文件为字符串再解析”的需求,也会在文件不存在时抛出错误。

二、json-write函数的问题与修复

你当前的json-write函数里,(pprint (json out))是完全错误的——json不是合法的函数调用,而且你漏掉了最关键的一步:把Lisp的JSON对象序列化成符合JSON语法的字符串。

假设你使用的JSON库提供了类似json-stringify的序列化函数(比如常见的cl-json库用json:encode-json-to-string),修复后的函数可以这样写:

(defun json-write (json filename)
  (with-open-file (out filename
                       :direction :output
                       :if-exists :overwrite
                       :if-does-not-exist :create
                       :external-format :utf-8) ; 建议指定UTF-8编码,避免中文等字符乱码
    (write-string (json-stringify json) out) ; 替换成你实际使用的序列化函数
    filename)) ; 按照需求返回传入的文件名

如果你的JSON库支持直接向输出流序列化(比如cl-json的json:encode-json),也可以直接写入流:

(defun json-write (json filename)
  (with-open-file (out filename
                       :direction :output
                       :if-exists :overwrite
                       :if-does-not-exist :create
                       :external-format :utf-8)
    (json:encode-json json out) ; 适配cl-json库的写法
    filename))

对你的两个问题的解答

  1. 你的函数是否部分正确?
    • json-load的整体思路(读文件内容→解析)是对的,但变量作用域、参数传递的逻辑完全错误;json-write里的with-open-file参数设置(输出方向、覆盖/创建规则)是正确的,但核心的序列化写入部分完全不符合要求。
  2. 如何将JSON对象以JSON语法写入文件?
    • 核心步骤是:先利用JSON库的序列化函数,把Lisp中的JSON对象转换成标准JSON格式的字符串(或者直接写入输出流),再通过write-string或者库提供的流写入方法,把内容写入到打开的文件流中。

测试预期用法

修复后,你预期的调用逻辑就能正常工作了:

CL-PROMPT> (json-load (json-write '(json-obj #| stuff |#) "foo.json"))
; 会返回对应的(json-obj #| stuff |#)对象,前提是你的序列化/反序列化函数能正确处理这个对象

内容的提问来源于stack exchange,提问作者Giuseppe Giubaldo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:08:16