Skip to content

fix: reject an unresolved node reference instead of keeping it as a string - #79

Merged
swordqiu merged 1 commit into
yunionio:masterfrom
swordqiu:hotfix/qj-reject-node-ref
Sep 16, 2026
Merged

swordqiu merged 1 commit into
yunionio:masterfrom
swordqiu:hotfix/qj-reject-node-ref

Conversation

@swordqiu

Copy link
Copy Markdown
Member

依赖 #77,请先合并 #77(本分支基于它)。

背景

#77 让默认入口不再解析节点引用,但未解析的裸 <N> 会回落成普通字符串。调用方拿到 "<1>" 时,无法与真的就是字符串 "<1>" 的数据区分 —— 有类型目标会报类型错误,但 map[string]interface{} / JSONObject 这类无类型目标会静默接受。

典型触发路径:Marshal 对循环结构写出引用语法,再用默认入口 Parse 读回。

变更

默认入口遇到格式正确的节点引用(裸 <N>,N 为整数)时返回 ErrNodeReferenceDisabled,而不是降级为字符串。这类 token 本就不是合法 JSON,标准解析器同样拒绝。

  • 只拒绝 <整数> 形式;带引号的 "<1>"、以及 <abc> 这类非引用 token 行为不变
  • 受信任入口 ParseTrusted 不受影响

同时给 Marshal 补上文档注释,说明循环结构会写出本库扩展语法、产出的不是合法 JSON、需用 ParseTrusted 读回。

兼容性影响

含裸 <N> 的文档(非标准 JSON)此前能解析成功,现在返回错误。忽略 Parse 错误并直接解引用返回值的调用方会遇到 nil 解引用崩溃 —— 但这类输入本就是非法 JSON,且同样的模式对畸形输入(如 {"a":})早已存在(Parse 返回 nil, err)。

测试

node_reference_test.go

  • TestNodeReferenceRejected:4 种含引用的文档必须报错;带引号的 "<1>"<abc> 仍正常解析
  • TestNodeIdKeyIsOrdinary:不含引用时 ___jnid_ 仍是普通键、nodeId 保持 0
  • 既有 TestMarshalUnmarshalKeepsCycle / TestParseTrustedResolvesReference / TestParseTrustedRoundTrip 不变,确认受信任路径能力完整

go test ./... 全量通过。

…tring

A bare <N> value that is not resolved used to be kept as a plain string,
which a caller could not tell apart from a real string.  The document is
not valid json either way, so report it.

Only a well formed <N> with an integer N is rejected, a quoted value and
a token that is not a reference are unaffected.

Marshal keeps writing the reference syntax for a cyclic object, its doc
comment now says so.
@swordqiu
swordqiu merged commit a265ce7 into yunionio:master Sep 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant