Subject: bug#40693: 28.0.50; json-encode-alist changes alist

From: Ivan Andrus <[email-masked]>
Date: Fri, 17 Apr 2020 20:59:54 -0600

I recently filed #40692 (https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40692) about a problem I was having with magit forge using creating the wrong title because an alist created in a function contained a single constant at the end and it was being changed every time.  I still find it surprising that a back-quoted list would behave that way, but I suspect it will be considered desired, or at least expected behavior.

I was able to track it down to the actual function that was causing the change: json-encode-alist when json-encoding-object-sort-predicate is set.  I have it set, and indeed it's extremely useful to view JSON that in a meaningful order.  I don't think that anyone would expect that encoding json would change the underlying data, so I think json-encode-alist should be changed to make a copy to avoid this situation.

  (require 'json)

  (defun fun-withdraw (amount)
    (json-encode-alist
     `((tamount . , amount)
       (const . some-constant))))

  (fun-withdraw 12) ;; Run this a few times and nothing will change

  (setq json-encoding-object-sort-predicate #'string<)

  (fun-withdraw 12) ;; Now it will change every time

It's late now, but if I have some time in the next few days, I may submit a patch since it seems like a simple enough change.

-Ivan

In GNU Emacs 28.0.50 (build 18, x86_64-apple-darwin18.7.0, NS appkit-1671.60 Version 10.14.6 (Build 18G4032))
of 2020-04-10 built on iandrus-macOS
Repository revision: 965390ca5f206c6358014574fe5140ba40850391
Repository branch: master
Windowing system distributor 'Apple', version 10.3.1671
System Description:  Mac OS X 10.14.6

Configured using:
'configure
PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig
--with-sound=yes --with-ns --with-modules --with-file-notification=yes
--enable-gcc-warnings=warn-only --with-xpm --with-jpeg --with-tiff
--with-gif --with-png --with-rsvg --with-xml2 --with-imagemagick
--with-json --with-xft --with-libotf --with-gnutls=no --with-makeinfo
--with-libgmp'

Configured features:
RSVG IMAGEMAGICK GLIB NOTIFY KQUEUE ACL LIBXML2 ZLIB TOOLKIT_SCROLL_BARS
XIM NS MODULES THREADS JSON PDUMPER GMP

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Features:
(mailalias mailclient shadow emacsbug sendmail calc-bin calc-yank
gap-smie gap-mode gap-process sage-shell-mode deferred cursor-sensor
ess-r-mode ess-r-flymake ess-r-xref ess-trns ess-r-package
ess-r-completion ess-roxy ess-r-syntax ess-rd ess-s-lang ess-help
ess-mode ess-inf ess-tracebug ess ess-utils ess-custom disass calc-vec
calccomp calc-aent all-the-icons-faces data-material data-weathericons
data-octicons data-fileicons data-faicons data-alltheicons
buttercup-compat cider-find cider-scratch apropos array jsonrpc
jupyter-org-extensions jupyter-rest-api jupyter-org-client jupyter-repl
jupyter-kernel-manager jupyter-channel jupyter-widget-client websocket
simple-httpd jupyter-kernelspec jupyter-env jupyter-client
jupyter-comm-layer jupyter-messages hmac-def jupyter-mime jupyter-base
lsp-html lsp-mode em-glob bindat treemacs org-inlinetask gnus-art mm-uu
mml2015 mm-view mml-smime smime dig ol-bibtex nnir gnus-sum gnus-group
gnus-undo gnus-start gnus-cloud nnimap nnmail mail-source utf7 netrc
nnoo gnus-spec gnus-int gnus-range gnus-win esh-mode doc-view bibtex
ob-octave eshell esh-cmd esh-ext esh-opt esh-proc esh-io esh-arg
esh-module esh-groups esh-util ebnf2ps ps-print ps-print-loaddefs ps-def
lpr cider cider-debug cider-inspector cider-browse-ns cider-mode
cider-completion cider-profile cider-eval cider-repl-history cider-repl
cider-resolve cider-test cider-overlays cider-stacktrace cider-doc
cider-browse-spec cider-clojuredocs cider-popup cider-eldoc cider-client
cider-common cider-util cider-connection sesman-browser nrepl-client
queue nrepl-dict cider-compat sesman clojure-mode parseedn
parseclj-parser parseclj-lex a ob-clojure calc-store calc-trail
org-attach finder perl6-repl pkg-info epl leaf treemacs-compatibility
treemacs-mode treemacs-bookmarks hydra lv thunk treemacs-interface
treemacs-extensions treemacs-persistence treemacs-mouse-interface
treemacs-tag-follow-mode treemacs-filewatch-mode treemacs-tags
treemacs-visuals treemacs-fringe-indicator pulse treemacs-faces
treemacs-follow-mode treemacs-rendering treemacs-async treemacs-icons
treemacs-themes treemacs-workspaces treemacs-scope treemacs-dom
treemacs-core-utils treemacs-macros treemacs-customization ace-window
pfuture inline term ehelp mail-extr compare-w axle vcursor texnfo-upd
texinfo mc-mark-more rnc-mode goto-last-change mc-separate-operations
align info-colors elisp-depmap-exec elisp-depmap-graph
elisp-depmap-parse elisp-depmap-secondhelp xwwp-follow-link xwwp xwidget
async-await iter2 promise promise-rejection-tracking promise-finally
promise-done promise-es6-extensions promise-core autoload tar-mode
arc-mode archive-mode lisp-mnt php-mode etags fileloop xref cc-langs
php-face php php-project projectile ibuf-ext ibuffer ibuffer-loaddefs
cmake-mode writeroom-mode visual-fill-column mixed-pitch vc-annotate
poly-markdown dockerfile-mode forge-list forge-commands forge-semi
forge-bitbucket buck forge-gogs gogs forge-gitea gtea forge-gitlab glab
forge-github ghub-graphql treepy gsexp ghub let-alist forge-notify
forge-revnote forge-pullreq forge-issue forge-topic forge-post
forge-repo forge forge-core forge-db closql emacsql-sqlite emacsql
emacsql-compiler snout-mode mhtml-mode css-mode eww mm-url gnus nnheader
url-queue shr svg find-file whitespace make-mode magit-imenu git-rebase
log-view novice vc-svn vc-cvs project deadgrep spinner lua-mode timezone
mm-archive plantuml-mode gnuplot-gui gnuplot python markdown-mode
edit-indirect conf-mode yaml-mode json-mode json-reformat json-snatcher
js sql view dabbrev inflections mc-edit-lines multiple-cursors-core sort
calc-arith calc-misc calc-math macros rot13 disp-table cperl-mode
hippie-exp org-forms cl-print calc-alg calc-menu calc-ext calc
calc-loaddefs calc-macs artist picture reporter rect ffap skeleton
tabify cal-move org-datetree org-capture sh-script org-duration
cal-julian lunar solar cal-dst cal-iso face-remap perl6-mode perl6-imenu
perl6-indent smie perl6-font-lock char-fold misearch multi-isearch
cap-words superword subword two-column executable bug-reference
magit-extras magit-bookmark magit-submodule magit-obsolete magit-popup
magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull
magit-fetch magit-clone magit-remote magit-commit magit-sequence
magit-notes magit-worktree magit-tag magit-merge magit-branch
magit-reset magit-files magit-refs magit-status magit magit-repos
magit-apply magit-wip magit-log magit-diff smerge-mode diff magit-core
magit-autorevert magit-margin magit-transient magit-process magit-mode
git-commit transient magit-git magit-section magit-utils writegood-mode
log-edit message rfc822 mml mml-sec gnus-util rmail rmail-loaddefs
mm-decode mm-bodies mailabbrev gmm-utils mailheader pcvs-util
with-editor async-bytecomp async vc vc-dispatcher add-log
ido-completing-read+ memoize cus-edit minibuf-eldef gvol-light-theme
elide-head highlight-tail hl-sexp highlight-symbol adafruit-wisdom
org-eldoc reveal epa-file epa epg epg-config request mail-utils flyspell
ispell poly-org polymode derived poly-lock polymode-base polymode-weave
polymode-export polymode-compat polymode-methods polymode-core
polymode-classes eieio-custom color org-archive eieio-opt speedbar
dframe tls gnutls network-stream url-http url-gw nsm rmc puny url-cache
url-auth url url-proxy url-privacy url-expand url-methods url-history
url-cookie url-domsuf dad-joke time semantic/idle semantic/analyze
semantic/sort semantic/scope semantic/analyze/fcn semantic/db eieio-base
semantic/format ezimage semantic/tag-ls semantic/find semantic/ctxt
org-drill persist org-id org-tempo tempo org-protocol org-mouse
org-habit org-ctags ob-latex ob-gnuplot ob-plantuml ob-js vc-git
diff-mode rng-xsd xsd-regexp rng-cmpct hideshow rng-nxml rng-valid
nxml-mode nxml-outln nxml-rap sgml-mode dom perl6-detect which-func
paren semantic/util-modes semantic/util semantic semantic/tag
semantic/lex semantic/fw mode-local cedet saveplace msb mb-depth
icomplete gud hl-line autorevert filenotify cus-start cus-load helpful
imenu trace edebug f dash-functional help-fns radix-tree elisp-refs loop
avy autoinsert cl-extra yasnippet find-file-in-repository smex ido
flycheck-clang-analyzer flycheck rtags popup repeat docker-tramp
kubernetes-tramp tramp-cache tramp-okta tramp-sh tramp tramp-loaddefs
trampver tramp-integration files-x tramp-compat parse-time iso8601
ls-lisp asm-mode info-look cc-mode cc-fonts cc-guess cc-menus cc-cmds
cc-styles cc-align cc-engine cc-vars cc-defs bookmark
text-property-search beacon fold ripgrep wgrep grep literal-string
ox-pandoc ht ox-org ox-odt rng-loc rng-uri rng-parse rng-match rng-dt
rng-util rng-pttrn nxml-parse nxml-ns nxml-enc xmltok nxml-util ox-latex
ox-icalendar ox-html table ox-ascii ox-publish ox org-element avl-tree
generator org-wc idle-org-agenda org-mac-link org-mobile org-agenda
diary-lib diary-loaddefs org-crypt ob-obxml oberon-shell-mode ob-shell
shell ob-python org-clock orgtbl-ascii-plot org ob ob-tangle ob-ref
ob-lob ob-table ob-exp org-macro org-footnote org-src ob-comint
org-pcomplete pcomplete org-list org-faces org-entities time-date
noutline outline org-version ob-emacs-lisp ob-core ob-eval org-table ol
org-keys org-compat org-macs org-loaddefs cal-menu calendar cal-loaddefs
sage jka-compr xml preview prv-emacs tex-buf latex latex-flymake
flymake-proc flymake compile comint ansi-color ring warnings thingatpt
tex-ispell tex-style tex crm edit-server elnode dired+ image-dired
image-mode exif format-spec image-file dired-x dired-aux dired
dired-loaddefs db web time-stamp s url-util mailcap mm-encode mail-parse
rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr fakir dotassoc kv
noflet cl-indent dash ert ewoc debug backtrace help-mode find-func
savehist desktop frameset drag-stuff recentf tree-widget wid-edit
browse-kill-ring delsel backtr keyfreq uptimes pp server assoc advice
windmove finder-inf package-x tab-line pcase easy-mmode cl rx tex-site
info edmacro kmacro package easymenu browse-url url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs
password-cache json subr-x map url-vars seq byte-opt gv bytecomp
byte-compile cconv cl-loaddefs cl-lib tooltip eldoc electric uniquify
ediff-hook vc-hooks lisp-float-type mwheel term/ns-win ns-win
ucs-normalize mule-util term/common-win tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode elisp-mode
lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch
timer select scroll-bar mouse jit-lock font-lock syntax facemenu
font-core term/tty-colors frame minibuffer cl-generic cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european
ethiopic indian cyrillic chinese composite charscript charprop
case-table epa-hook jka-cmpr-hook help simple abbrev obarray
cl-preloaded nadvice loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote threads kqueue cocoa ns
multi-tty make-network-process emacs)