improve json marshaling/unmarshaling
This commit is contained in:
parent
40b754668d
commit
c85efdc49f
18
document.go
18
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
|
||||
|
9
model.go
9
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)
|
||||
|
65
query.go
65
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,12 +389,25 @@ func rerere(input interface{}, resType reflect.Type) interface{} {
|
||||
resType = resType.Elem()
|
||||
}
|
||||
var resV reflect.Value
|
||||
newInstance := ModelRegistry.newForType(resType)
|
||||
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
|
||||
if rve.Kind() == reflect.Pointer {
|
||||
@ -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 {
|
||||
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()
|
||||
}
|
||||
@ -533,8 +572,14 @@ func handleAnon(raw interface{}, rtype reflect.Type, rval reflect.Value) reflect
|
||||
}
|
||||
if valueField.Kind() == reflect.Pointer {
|
||||
valueField.Elem().Set(reflect.ValueOf(fval))
|
||||
} else {
|
||||
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))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
registry.go
12
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user