diff --git a/document.go b/document.go index 91f3eee..5c57ef7 100644 --- a/document.go +++ b/document.go @@ -2,6 +2,7 @@ package orm import ( "encoding/json" + "fmt" "go.mongodb.org/mongo-driver/v2/bson" "log" "reflect" @@ -33,13 +34,24 @@ func (d *Document) UnmarshalJSON(bytes []byte) error { err = json.Unmarshal(bytes, &tmpV) typ := reflect.SliceOf(d.model.Type) //d.SetSelf() - rerere(tmpV, typ) + var arr []interface{} + reified := rerere(tmpV, typ, true) + if ta, ok := reified.(bson.A); ok { + arr = []interface{}(ta) + } else { + arr = reified.([]interface{}) + } + fmt.Println(len(arr)) break case map[string]interface{}: tmpV := make(bson.M) err = json.Unmarshal(bytes, &tmpV) - typ := d.model.Type - rerere(tmpV, typ) + typ := reflect.PointerTo(d.model.Type) + self := reflect.ValueOf(d.self) + nself := reflect.NewAt(typ.Elem(), self.UnsafePointer()) + reified := rerere(tmpV, typ, true) + nself.Elem().Set(reflect.ValueOf(reified).Elem()) + d.self = nself.Interface() break } return err diff --git a/model.go b/model.go index 435acae..bfae4ce 100644 --- a/model.go +++ b/model.go @@ -217,14 +217,15 @@ func createBase(d any) (reflect.Value, int, string) { v := valueOf(d) i := ModelRegistry.Index(n) - r := reflect.New(t) + r := reflect.New(reflect.PointerTo(t)).Elem() + r.Addr().Elem().Set(reflect.New(t)) - r.Elem().Set(v) + r.Addr().Elem().Elem().Set(v) if reflect.ValueOf(d).Kind() == reflect.Pointer { - r.Elem().Set(reflect.ValueOf(d).Elem()) + r.Addr().Elem().Elem().Set(reflect.ValueOf(d).Elem()) } else { - r.Elem().Set(reflect.ValueOf(d)) + r.Addr().Elem().Elem().Set(reflect.ValueOf(d)) } ri.setTypeName(n) r.Interface().(IDocument).setModel(*ri) diff --git a/query.go b/query.go index 5b17ffd..e50fd41 100644 --- a/query.go +++ b/query.go @@ -10,6 +10,7 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" "reflect" "strings" + "time" ) type Query struct { @@ -176,7 +177,7 @@ func populate(r Reference, rcoll string, rawDoc interface{}, d string, src inter if !errors.Is(reso.Err(), mongo.ErrNoDocuments) { var anotherMap = make(bson.M) reso.Decode(&anotherMap) - reflect.ValueOf(t).Elem().Set(reflect.ValueOf(rerere(anotherMap, tto)).Elem()) + reflect.ValueOf(t).Elem().Set(reflect.ValueOf(rerere(anotherMap, tto, false)).Elem()) t.setRaw(anotherMap) } hatred := rv @@ -338,12 +339,12 @@ func (q *Query) reOrganize() { } slic := reflect.New(reflect.SliceOf(typ)) for _, v2 := range arr { - inter := reflect.ValueOf(rerere(v2, typ)) + inter := reflect.ValueOf(rerere(v2, typ, false)) slic.Elem().Set(reflect.Append(slic.Elem(), inter)) } trvo = slic.Elem() } else { - trvo = reflect.ValueOf(rerere(q.rawDoc, reflect.TypeOf(q.doc))) + trvo = reflect.ValueOf(rerere(q.rawDoc, reflect.TypeOf(q.doc), false)) } resV := reflect.ValueOf(q.doc) @@ -365,9 +366,15 @@ func (q *Query) reOrganize() { } } -func rerere(input interface{}, resType reflect.Type) interface{} { +func rerere(input interface{}, resType reflect.Type, isJson bool) interface{} { t := reflect.TypeOf(input) v := reflect.ValueOf(input) + var key string + if isJson { + key = "json" + } else { + key = "bson" + } if input == nil { return nil } @@ -382,11 +389,24 @@ func rerere(input interface{}, resType reflect.Type) interface{} { resType = resType.Elem() } var resV reflect.Value - newInstance := ModelRegistry.newForType(resType) - if newInstance == nil { - resV = reflect.New(resType) - } else { + var newInstance interface{} + if _, _, has := ModelRegistry.Has(reflect.New(resType).Elem().Interface()); has { + newInstance = Create(reflect.New(resType).Elem().Interface()) resV = reflect.ValueOf(newInstance) + } else { + newInstance = ModelRegistry.newForType(resType) + if newInstance == nil && resType.Kind() == reflect.Pointer { + newInstance = ModelRegistry.newForType(resType.Elem()) + if newInstance == nil { + resV = reflect.New(resType) + } else { + resV = reflect.ValueOf(newInstance) + } + } else if newInstance != nil { + resV = reflect.ValueOf(newInstance) + } else { + resV = reflect.New(resType) + } } var rve = resV @@ -407,6 +427,12 @@ func rerere(input interface{}, resType reflect.Type) interface{} { case reflect.Struct: shouldBreak := false mipmap, ok := v.Interface().(bson.M) + if !ok { + var omap map[string]interface{} + if omap, ok = v.Interface().(map[string]interface{}); ok { + mipmap = bson.M(omap) + } + } if ok { for i := 0; i < resType.NumField(); i++ { ft := resType.Field(i) @@ -417,7 +443,7 @@ func rerere(input interface{}, resType reflect.Type) interface{} { } tags, err := structtag.Parse(string(ft.Tag)) panik(err) - btag, err := tags.Get("bson") + btag, err := tags.Get(key) if err != nil { continue } @@ -431,7 +457,7 @@ func rerere(input interface{}, resType reflect.Type) interface{} { if ttmp, tok := intermediate.(bson.DateTime); tok { tmp = ttmp.Time() } else { - tmp = rerere(intermediate, ft.Type) + tmp = rerere(intermediate, ft.Type, isJson) } fuck := reflect.ValueOf(tmp) if tmp != nil { @@ -446,7 +472,7 @@ func rerere(input interface{}, resType reflect.Type) interface{} { if tt.Kind() == reflect.Pointer { tt = tt.Elem() } - tmp := rerere(intermediate, ft.Type) + tmp := rerere(intermediate, ft.Type, isJson) if tmp != nil { if reflect.ValueOf(tmp).Kind() == reflect.Pointer && fv.Kind() != reflect.Pointer { fv.Set(reflect.ValueOf(tmp).Elem()) @@ -463,7 +489,14 @@ func rerere(input interface{}, resType reflect.Type) interface{} { nunu := ModelRegistry.new_(resType.Name()) ider, ok := nunu.(HasID) if ok { - ider.SetId(v.Interface()) + toConvert := reflect.ValueOf(ider.Id()).Type() + if v.Type() != toConvert { + if v.CanConvert(toConvert) { + ider.SetId(v.Convert(toConvert).Interface()) + } + } else { + ider.SetId(v.Interface()) + } if reflect.ValueOf(ider).Kind() == reflect.Pointer { nunu = reflect.ValueOf(ider).Elem().Interface() } @@ -471,10 +504,16 @@ func rerere(input interface{}, resType reflect.Type) interface{} { } } case reflect.Slice: - arr := v.Interface().(bson.A) + _, aOk := v.Interface().(bson.A) + var arr []interface{} + if !aOk { + arr = v.Interface().([]interface{}) + } else { + arr = []interface{}(v.Interface().(bson.A)) + } for _, it := range arr { if it != nil { - tmp := reflect.ValueOf(rerere(it, rve.Type().Elem())) + tmp := reflect.ValueOf(rerere(it, rve.Type().Elem(), isJson)) if tmp.Kind() == reflect.Pointer { tmp = tmp.Elem() } @@ -534,7 +573,13 @@ func handleAnon(raw interface{}, rtype reflect.Type, rval reflect.Value) reflect if valueField.Kind() == reflect.Pointer { valueField.Elem().Set(reflect.ValueOf(fval)) } else { - valueField.Set(reflect.ValueOf(fval)) + if reflect.TypeOf(fval) == reflect.TypeFor[string]() && typeField.Type == reflect.TypeFor[time.Time]() { + tt, _ := time.Parse(time.RFC3339, fval.(string)) + valueField.Set(reflect.ValueOf(tt)) + } else { + valueField.Set(reflect.ValueOf(fval)) + + } } } } diff --git a/registry.go b/registry.go index 9ff8df8..af8e002 100644 --- a/registry.go +++ b/registry.go @@ -227,9 +227,13 @@ func (r TModelRegistry) Index(n string) int { func (r TModelRegistry) new_(n string) interface{} { if name, m, ok := ModelRegistry.HasByName(n); ok { v := reflect.New(m.Type) - df := v.Elem().Field(m.idx) + av := reflect.New(reflect.PointerTo(m.Type)).Elem() + av.Addr().Elem().Set(v) + df := av.Addr().Elem().Elem().Field(m.idx) + ado := reflect.New(reflect.PointerTo(df.Type())).Elem() do := reflect.New(df.Type()) - d := do.Interface().(IDocument) + ado.Addr().Elem().Set(do) + d := ado.Addr().Elem().Interface().(IDocument) d.newPopulationMap() //d := df.Interface().(IDocument) for k := range m.references { @@ -237,9 +241,9 @@ func (r TModelRegistry) new_(n string) interface{} { } d.setModel(*m) d.getModel().typeName = name - d.SetSelf(do.Interface()) + d.SetSelf(av.Interface()) df.Set(reflect.ValueOf(d).Elem()) - return v.Interface() + return av.Interface() } return nil }