-
Notifications
You must be signed in to change notification settings - Fork 369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ast.Node should support Set variant that sets at any depth, creating objects and arrays as needed #730
Comments
Here's a rough draft of something that might work externally, but I'm sure it could be written nicer if internal: package deepset
import (
"github.com/bytedance/sonic/ast"
"slices"
)
// GetByPathDeep load given path on demands,
// which only ensure nodes before this path got parsed.
//
// Note, the api expects the json is well-formed at least,
// otherwise it may return unexpected result.
func GetByPathDeep(self *ast.Node, path ...interface{}) *ast.Node {
var s = self
for _, p := range path {
switch p := p.(type) {
case int:
if !s.Exists() {
*s = ast.NewArray(slices.Repeat([]ast.Node{ast.NewNull()}, p+1))
} else {
if ln, err := s.Len(); err == nil && ln <= p {
for range p + 1 - ln {
if err = s.Add(ast.NewNull()); err != nil {
break
}
}
}
}
s = s.Index(p)
case string:
if !s.Exists() {
*s = ast.NewObject([]ast.Pair{ast.NewPair(p, ast.Node{})})
} else {
if v := s.Get(p); !v.Exists() {
_, _ = s.Set(p, ast.Node{})
}
}
s = s.Get(p)
default:
panic("path must be either int or string")
}
}
return s
}
func SetByPath(self *ast.Node, v ast.Node, path ...any) {
*GetByPathDeep(self, path...) = v
} |
ok,we will look forward it. But |
Absolutely agree that GetByPath shouldn't modify anything… so maybe that |
@scr-oath BTW, I'm working on another business now... Are you interested in submitting PRs? We are glad to see there are more contributors! |
Some use-cases use a combination of gjson and sjson with paths deeper than just a key to alter incoming json data to be fuzzy with a schema - making it "fit" even if clients are at various levels of "compliance" vs correctness, in the spirit of "be generous in what you receive and strict with what you output".
https://github.com/cloudwego/gjson can be useful for the gjson side, but there is no corresponding sjson side. In addition, I'm curious if the ast framework could be good at holding the entire tree and making updates or additions at any level with a more convenient variant of Set, which could create objects and arrays as needed to make a place for the value to sit.
The current state of the module would seemingly require a client to, for every non-leaf key/value do a get and, if !Exists, set to the appropriate type and call either Set or Add as needed for Object v. Array. - while doable, it seems like something that could be made MUCH more convenient and a "pit of success" for clients to use properly/efficiently.
The ultimate hope would be to be able to combinations of get and set on the root structure, without having to re-parse (even lazily) the entire content over and over again, like is needed for gjson/sjson - if updates are made with sjson and return a new
[]byte
then gjson would have to re-read that on subsequent gets to decide further updates/corrections/etcThe text was updated successfully, but these errors were encountered: