package json import ( "bytes" "encoding/json" "fmt" "io" "io/ioutil" "log" "reflect" "git.ali33.ru/fcg-xvii/go-tools/containers" ) type JSONTokenType byte const ( JSON_INVALID JSONTokenType = iota JSON_ARRAY JSON_OBJECT JSON_VALUE ) func (s JSONTokenType) String() string { switch s { case JSON_INVALID: return "JSON_INVALID" case JSON_ARRAY: return "JSON_ARRAY" case JSON_OBJECT: return "JSON_OBJECT" case JSON_VALUE: return "JSON_VALUE" default: return "JSON_UNDEFINED" } } func Decode(r io.Reader, obj interface{}) error { dec := InitJSONDecoder(r) return dec.Decode(obj) } func DecodeBytes(src []byte, obj interface{}) error { buf := bytes.NewBuffer(src) dec := InitJSONDecoder(buf) return dec.Decode(obj) } // JSON decode interfaces type Type byte const ( TypeUndefined Type = iota TypeInterface TypeObject TypeSlice ) type JSONInterface interface { JSONDecode(*JSONDecoder) (isNil bool, err error) } type JSONObject interface { JSONField(fieldName string, storeTemp Map) (fieldPtr interface{}, err error) } type JSONFinisher interface { JSONFinish(storeTemp Map) error } func (s *JSONDecoder) JSONTypeCheck(rv *reflect.Value) (t Type) { // check slice iface := rv.Interface() if _, check := iface.(JSONInterface); check { // check JSONInterface t = TypeInterface return } else if _, check = iface.(JSONObject); check { // check JSONObject t = TypeObject return } return } /////////////////////////////////////////////// func InitJSONDecoderFromSource(src []byte) *JSONDecoder { r := bytes.NewReader(src) return InitJSONDecoder(r) } func InitJSONDecoder(r io.Reader) *JSONDecoder { return &JSONDecoder{ Decoder: json.NewDecoder(r), embedded: containers.NewStack(0), } } type JSONDecoder struct { *json.Decoder token json.Token embedded *containers.Stack current JSONTokenType objectkey bool objectClosed bool parentObj reflect.Value err error counter int } func (s *JSONDecoder) buf() { b, _ := ioutil.ReadAll(s.Buffered()) log.Println(">>>", string(b)) } func (s *JSONDecoder) IsObjectKey() bool { return s.objectkey } func (s *JSONDecoder) IsObjectClosed() bool { return s.objectClosed } func (s *JSONDecoder) Current() JSONTokenType { return s.current } func (s *JSONDecoder) EmbeddedLevel() int { return s.embedded.Len() } func (s *JSONDecoder) Token() (t json.Token, err error) { s.objectClosed = false if t, err = s.Decoder.Token(); err == nil { if delim, check := t.(json.Delim); check { s.objectkey = false switch delim { case '{': s.embedded.Push(JSON_OBJECT) s.current = JSON_OBJECT case '[': s.embedded.Push(JSON_ARRAY) s.current = JSON_ARRAY case '}', ']': s.embedded.Pop() s.objectClosed, s.current = true, JSON_INVALID if s.embedded.Len() > 0 { s.current = s.embedded.Peek().(JSONTokenType) } } } else { if s.current == JSON_OBJECT { s.objectkey = !s.objectkey } s.current = JSON_VALUE } } s.token = t return } func (s *JSONDecoder) Next() error { if _, err := s.Token(); err != nil { return err } switch s.current { case JSON_ARRAY, JSON_OBJECT: { stackLen := s.embedded.Len() for s.embedded.Len() >= stackLen { if _, err := s.Token(); err != nil { return err } } return nil } default: return nil } } func (s *JSONDecoder) DecodeRaw(v interface{}) error { return s.Decoder.Decode(v) } func (s *JSONDecoder) Decode(v interface{}) (err error) { rv := reflect.ValueOf(v) err = s.decodeReflect(&rv) return } func (s *JSONDecoder) decodeReflect(rv *reflect.Value) (err error) { switch s.JSONTypeCheck(rv) { case TypeInterface: { if rv.Kind() == reflect.Ptr && rv.IsNil() { rv.Set(reflect.New(rv.Type().Elem())) } var isNil bool if isNil, err = rv.Interface().(JSONInterface).JSONDecode(s); err == nil { if isNil && rv.CanAddr() { rv.Set(reflect.Zero(rv.Type())) } } return } case TypeObject: return s.decodeJSONObject(rv) case TypeSlice: return s.decodeSlice(rv) default: { if rv.Kind() == reflect.Ptr { ev := rv.Elem() if !ev.IsValid() { ev = reflect.Indirect(reflect.New(rv.Type())) ev.Set(reflect.New(ev.Type().Elem())) if err = s.decodeReflect(&ev); err == nil && !ev.IsNil() { rv.Set(ev) } return } else { if ev.Kind() == reflect.Ptr { return s.decodeReflect(&ev) } else if ev.Kind() == reflect.Slice { return s.decodeSlice(&ev) } else if ev.Kind() == reflect.Struct { return s.decodeRawObject(rv) } } } return s.Decoder.Decode(rv.Interface()) } } } func fieldConvert(v reflect.Value, t reflect.Type, fieldName string) (val reflect.Value, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v :: %v", fieldName, r.(string)) } }() val = v.Convert(t) return } func (s *JSONDecoder) decodeRawObject(rv *reflect.Value) (err error) { var t json.Token // chek first token is object if t, err = s.Token(); err != nil { return } if s.current != JSON_OBJECT { // check null token if t == nil { if rv.Kind() == reflect.Ptr && !rv.IsNil() { rv.Set(reflect.Zero(rv.Type())) } return } // token is not object return fmt.Errorf("EXPCTED OBJECT, NOT %T", t) } if rv.Kind() == reflect.Ptr { if rv.IsNil() { rv.Set(reflect.New(rv.Type().Elem())) } elem := rv.Elem() rv = &elem } el := s.EmbeddedLevel() for el <= s.EmbeddedLevel() { if t, err = s.Token(); err != nil { return } if s.Current() == JSON_VALUE && s.IsObjectKey() { s.buf() if f := rv.FieldByName(t.(string)); f.IsValid() { rrv := reflect.New(f.Type()) if err = s.decodeReflect(&rrv); err != nil { return } if !rrv.IsNil() { f.Set(rrv.Elem()) } } else { var i interface{} s.Decoder.Decode(&i) } } } return } // slice func (s *JSONDecoder) decodeSlice(rv *reflect.Value) (err error) { var t json.Token if t, err = s.Token(); err != nil { return } if s.current != JSON_ARRAY { if t == nil { if !rv.IsNil() { rv.Set(reflect.Zero(rv.Type())) } return } return fmt.Errorf("EXPCTED SLICE, NOT %T", t) } // check slice is nil if rv.IsNil() { rv.Set(reflect.MakeSlice(rv.Type(), 0, 0)) } elemType := reflect.TypeOf(rv.Interface()).Elem() for s.More() { em := reflect.New(elemType) if err = s.decodeReflect(&em); err != nil { return } rv.Set(reflect.Append(*rv, em.Elem())) } if _, err = s.Token(); err != nil { return } if d, check := s.token.(json.Delim); !check || d != ']' { return fmt.Errorf("JSON PARSE ERROR :: EXPECTED ']', NOT %v", d) } return } //////////////////////////////////////// func (s *JSONDecoder) decodeJSONObject(rv *reflect.Value) (err error) { var t json.Token // chek first token is object if t, err = s.Token(); err != nil { return } if s.current != JSON_OBJECT { // check null token if t == nil { if rv.CanAddr() && !rv.IsNil() { rv.Set(reflect.Zero(rv.Type())) } return } // token is not object return fmt.Errorf("EXPCTED OBJECT, NOT %T", t) } // check null pounter in source object if rv.Kind() == reflect.Ptr && rv.IsNil() { // create new object rv.Set(reflect.New(rv.Type().Elem())) } el, obj, store := s.EmbeddedLevel(), rv.Interface().(JSONObject), NewMap() var fieldPtr interface{} for el <= s.EmbeddedLevel() { if t, err = s.Token(); err != nil { return } if s.Current() == JSON_VALUE && s.IsObjectKey() { if fieldPtr, err = obj.JSONField(t.(string), store); err != nil { return } if fieldPtr != nil { rv := reflect.ValueOf(fieldPtr) if err = s.decodeReflect(&rv); err != nil { return } } else { if err = s.Next(); err != nil { return } } } } if finisher, check := rv.Interface().(JSONFinisher); check { err = finisher.JSONFinish(store) } return }