首页 > 解决方案 > st-json:write-json - 避免浮点数的指数标记

问题描述

(st-json:write-json-to-string
  (st-json:read-json "{\"a\":0.1}"))

输出不是有效的 JSON:

"{\"a\":1.e-1}"

期望的输出:

"{\"a\":0.1}"

write-json-to-string我在https://marijnhaverbeke.nl/st-json/上看不到任何选项或其他参数

如果这个数字稍微修改一下,我还是可以.10.10

更新:浮点格式有一个系统变量:“打印机在打印浮点数时*read-default-float-format*用于指导指数标记的选择。”

根据这个例子...

(let ((*read-default-float-format* 'double-float))
  (read-from-string "(1.0 1.0e0 1.0s0 1.0f0 1.0d0 1.0L0)"))

==> (1.0d0 1.0d0 1.0 1.0 1.0d0 1.0d0)

我正在使用的实现(SBCL 2.0.11)具有浮点格式 F 和 D。http://www.lispworks.com/documentation/lw50/CLHS/Body/v_rd_def.htm

我不确定“打印机*read-default-float-format*在打印浮点数时如何指导指数标记的选择”。...我下面的测试有问题吗?

 (progn
   (setf *read-default-float-format* 'long-float)
   (princ(st-json:write-json-to-string (st-json:read-json "{\"a\":0.1}")))
   (setf *read-default-float-format* 'single-float)
   (princ(st-json:write-json-to-string (st-json:read-json "{\"a\":0.1}")))
   (setf *read-default-float-format* 'double-float)
   (princ(st-json:write-json-to-string (st-json:read-json "{\"a\":0.1}")))
   (setf *read-default-float-format* 'short-float)
   (princ(st-json:write-json-to-string (st-json:read-json "{\"a\":0.1}"))))
   
 {"a":1.e-1}{"a":1.e-1}{"a":1.e-1}{"a":1.e-1}
 ==> "{\"a\":1.e-1}"

提前感谢您的帮助!

标签: common-lisp

解决方案


这与 . 无关*read-default-float-format*

在 SLIME 中使用M-.,我可以看到依次write-json-to-string调用.write-jsonwrite-json-element

write-json-element是一个泛型函数,针对不同类型有不同的方法。方法real是:

(defmethod write-json-element ((element real) stream)
  (format stream "~,,,,,,'eE" element))

该格式字符串是标准的 Common Lisp,导致您看到的行为。

CL-USER> (format t "~,,,,,,'eE" 0.1)
1.e-1
NIL
CL-USER> 

我不知道作者为什么这样做,但如果你坚持使用st-json,只需将方法重新定义为(这将发出重新定义警告,但忽略它):

(defmethod st-json:write-json-element ((element real) stream)
  (format stream "~F" element))

但是,如果您可以切换到另一个库,请查看jzon,它位于最新的 Quicklisp 中。


推荐阅读