package compiler import ( "bytes" "encoding/json" "fmt" "github.com/KromDaniel/jonson" ) type JSON []byte func (s JSON) Get(path ...string) ([]byte, error) { if s == nil { s = []byte("{}") } var ( root *jonson.JSON ) root, err := jonson.Parse(s) if err != nil { return nil, fmt.Errorf("parse root json: %w", err) } pointer := root for _, key := range path { // FIXME: we can traverse maps but not arrays (need to handle int keys) pointer = pointer.At(key) } // FIXME: use indent function from stdlib return pointer.ToJSON() } func (s JSON) Unset(path ...string) (JSON, error) { if s == nil { s = []byte("{}") } var ( root *jonson.JSON ) root, err := jonson.Parse(s) if err != nil { return nil, fmt.Errorf("unset: parse root json: %w", err) } var ( pointer = root pathDir []string ) if len(path) > 0 { pathDir = path[:len(path)-1] } for _, key := range pathDir { pointer = pointer.At(key) } if len(path) == 0 { pointer.Set(nil) } else { key := path[len(path)-1] pointer.DeleteMapKey(key) } return root.ToJSON() } func (s JSON) Set(valueJSON []byte, path ...string) (JSON, error) { if s == nil { s = []byte("{}") } var ( root *jonson.JSON value *jonson.JSON ) root, err := jonson.Parse(s) if err != nil { return nil, fmt.Errorf("parse root json: %w", err) } value, err = jonson.Parse(valueJSON) if err != nil { return nil, fmt.Errorf("SetJSON: parse value json: |%s|: %w", valueJSON, err) } var ( pointer = root pathDir []string ) if len(path) > 0 { pathDir = path[:len(path)-1] } for _, key := range pathDir { if !pointer.ObjectKeyExists(key) { pointer.MapSet(key, jonson.NewEmptyJSONMap()) } pointer = pointer.At(key) } if len(path) == 0 { pointer.Set(value) } else { key := path[len(path)-1] pointer.MapSet(key, value) } return root.ToJSON() } func (s JSON) String() string { if s == nil { return "{}" } return string(s) } func (s JSON) PrettyString() string { raw := s.String() b := &bytes.Buffer{} // If indenting fails, return raw string if err := json.Indent(b, []byte(raw), "", " "); err != nil { return raw } return fmt.Sprintf("%s\n", b.String()) }