feat(ast): add NodeFrom and Node.Unmarshal for struct/Node conversion#890
feat(ast): add NodeFrom and Node.Unmarshal for struct/Node conversion#890blueberrycongee wants to merge 3 commits intobytedance:mainfrom
Conversation
|
please move unrelated commit to another PR |
| // node, _ := sonic.Get(jsonBytes, "user") | ||
| // var user User | ||
| // err := node.Unmarshal(&user) | ||
| func (self *Node) Unmarshal(v interface{}) error { |
There was a problem hiding this comment.
If only such ineffecient implementation, Node.MarshalJSON()+ sonic.Unmarshal is enough. Consider using reflect to bind Node to Struct in place
| // } | ||
| // node, err := ast.NodeFrom(User{Name: "Alice", Age: 30}) | ||
| // name, _ := node.Get("name").String() // "Alice" | ||
| func NodeFrom(v interface{}) (Node, error) { |
There was a problem hiding this comment.
sonic.Marshal + Node.UnmarshalJSON() is simple enough. To get better performance, consider using reflect to bind Struct to Node in place
e6a5fcf to
dfaab7c
Compare
|
Thanks for the review! Here's what I've done: NodeFrom: I tested a pure reflection approach, but it was 2.6x slower than the JIT approach (3200 ns vs 1230 ns). Since sonic's JIT encoder/parser is highly optimized, I kept using Marshal + Parse. Unmarshal: Implemented with in-place reflection as suggested. It directly maps Node values to struct fields without intermediate JSON bytes, saving 72% memory (224B vs 794B). Benchmark results: NodeFrom: ~1237 ns/op (same as manual approach) |
…bytedance#733) - Add NodeFrom() to convert any Go value to a fully-parsed ast.Node - Add Node.Unmarshal() to decode Node back to Go value - Support both sonic (amd64/arm64) and encoding/json (fallback) implementations - Add comprehensive tests and benchmarks
- NodeFrom: use JIT (Marshal+Parse) for best performance - Unmarshal: use in-place reflection, saves 72% memory - Fix uint negative number handling - Add string tag support - Simplify comments to match sonic code style - Add comparison benchmarks
dfaab7c to
25f9ab1
Compare
What type of PR is this?
feat: A new feature
Check the PR title.
(Optional) Translate the PR title into Chinese.
新增 NodeFrom 和 Node.Unmarshal 方法,支持 Go 结构体与 ast.Node 的便捷互转
(Optional) More detailed description for this PR
en:
This PR adds two convenience APIs for converting between Go values and
ast.Node:ast.Node(*Node).Unmarshal(v interface{}) error- Decode anast.Nodeback to a Go valueUnlike
NewAny(), the Node returned by NodeFrom has a fully-parsed structure that supports all Get/Set operations.Benchmark Results:
The new API has ~7% overhead compared to manual approach, but provides a much cleaner interface.
zh(optional):
本 PR 新增两个便捷 API,用于 Go 值与
ast.Node之间的转换:ast.Node(*Node).Unmarshal(v interface{})- 将ast.Node解码回 Go 值与
NewAny()不同,NodeFrom 返回的 Node 是完整解析的,支持所有 Get/Set 操作。性能开销约 7%,换来更简洁的 API。
(Optional) Which issue(s) this PR fixes:
Fixes #733
(optional) The PR that updates user documentation:
N/A