go-hep.org/x/hep@v0.38.1/groot/rjson/rjson.go (about) 1 // Copyright ©2023 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package rjson contains tools to marshal ROOT objects to JSON. 6 package rjson // import "go-hep.org/x/hep/groot/rjson" 7 8 import ( 9 "bytes" 10 "encoding/json" 11 "fmt" 12 "io" 13 "reflect" 14 15 "go-hep.org/x/hep/groot/rbytes" 16 "go-hep.org/x/hep/groot/root" 17 ) 18 19 func Marshal(o root.Object) ([]byte, error) { 20 if o, ok := o.(rbytes.RSlicer); ok { 21 buf := new(bytes.Buffer) 22 enc := newEncoder(buf) 23 err := enc.Encode(o) 24 return buf.Bytes(), err 25 } 26 27 panic(fmt.Errorf("not implemented for %T", o)) 28 } 29 30 type encoder struct { 31 w io.Writer 32 } 33 34 func newEncoder(w io.Writer) *encoder { 35 return &encoder{w: w} 36 } 37 38 func (enc *encoder) encode(v any) error { 39 if v, ok := v.(rbytes.RSlicer); ok { 40 return enc.Encode(v) 41 } 42 43 var ( 44 err error 45 w = enc.w 46 rv = reflect.Indirect(reflect.ValueOf(v)) 47 ) 48 49 switch rv.Kind() { 50 case reflect.Slice: 51 _, err = w.Write([]byte("[")) 52 if err != nil { 53 return err 54 } 55 for i := range rv.Len() { 56 if i > 0 { 57 _, err := w.Write([]byte(",")) 58 if err != nil { 59 return err 60 } 61 } 62 err = enc.encode(rv.Index(i).Interface()) 63 if err != nil { 64 return err 65 } 66 } 67 _, err = w.Write([]byte("]")) 68 if err != nil { 69 return err 70 } 71 default: 72 raw, err := json.Marshal(v) 73 if err != nil { 74 return err 75 } 76 _, err = w.Write(raw) 77 if err != nil { 78 return err 79 } 80 } 81 82 return nil 83 } 84 85 func (enc *encoder) Encode(v rbytes.RSlicer) error { 86 mbrs := v.RMembers() 87 name := v.(root.Object).Class() 88 w := enc.w 89 _, err := fmt.Fprintf(w, "{%q: %q", "_typename", name) 90 if err != nil { 91 return err 92 } 93 for _, m := range mbrs { 94 _, err := fmt.Fprintf(w, ", %q: ", m.Name) 95 if err != nil { 96 return err 97 } 98 err = enc.encode(m.Value) 99 if err != nil { 100 return err 101 } 102 } 103 _, err = fmt.Fprintf(w, "}") 104 if err != nil { 105 return err 106 } 107 return nil 108 }