improve json marshaling/unmarshaling

This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2025-04-08 16:13:07 -04:00
parent 40b754668d
commit c85efdc49f
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
4 changed files with 88 additions and 26 deletions

View File

@ -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

View File

@ -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)

View File

@ -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))
}
}
}
}

View File

@ -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
}