func (n *Node) setType(ctx context.Context, t *system.Type) error { if t == nil { n.Type = nil n.JsonType = system.J_NULL n.UnderlyingRule = nil n.UnderlyingInnerType = nil return nil } if t.Interface { return kerr.New("VHOSYBMDQL", "Can't set type to an interface - must be concrete type.") } n.Type = t n.JsonType = t.NativeJsonType(ctx) if t.Alias != nil { rw := system.WrapRule(ctx, t.Alias) n.UnderlyingRule = rw uit := rw.InnerType(ctx) for uit.Alias != nil { uit = system.WrapRule(ctx, uit.Alias).InnerType(ctx) } n.UnderlyingInnerType = uit } else { n.UnderlyingRule = system.WrapEmptyRule(ctx, t) n.UnderlyingInnerType = t } return nil }
func (n *Node) setValue(ctx context.Context, in system.Packed, unpack bool) error { n.Missing = false objectType, err := extractType(ctx, in, n.Rule) if err != nil { return kerr.Wrap("MKMNOOYQJY", err) } if err := n.setType(ctx, objectType); err != nil { return kerr.Wrap("BCMOTEMUJE", err) } if n.Rule == nil && objectType != nil { n.Rule = system.WrapEmptyRule(ctx, objectType) } if in.Type() == system.J_MAP && n.Type.IsNativeObject() { // for objects and maps, Type() from the system.Packed is always J_MAP, // so we correct it for object types here. n.JsonType = system.J_OBJECT } else { n.JsonType = in.Type() } n.Null = in.Type() == system.J_NULL // validate json type // if !n.Null && n.Type.NativeJsonType() != n.JsonType { // return kerr.New("VEPLUIJXSN", "json type is %s but object type is %s", n.JsonType, n.Type.NativeJsonType()) // } if unpack { if n.Rule.Struct == nil { if err := system.Unpack(ctx, in, &n.Value); err != nil { return kerr.Wrap("CQMWGPLYIJ", err) } } else { t, err := n.Rule.GetReflectType() if err != nil { return kerr.Wrap("DQJDYPIANO", err) } var val reflect.Value if t.Kind() == reflect.Ptr { val = reflect.New(t.Elem()) } else { val = reflect.New(t).Elem() } if err := system.UnpackRefelctValue(ctx, in, val); err != nil { return kerr.Wrap("PEVKGFFHLL", err) } n.Value = val.Interface() } n.setVal(reflect.ValueOf(n.Value)) } switch n.Type.NativeJsonType(ctx) { case system.J_STRING: if in.Type() == system.J_MAP { n.ValueString = in.Map()["value"].String() } else { n.ValueString = in.String() } case system.J_NUMBER: if in.Type() == system.J_MAP { n.ValueNumber = in.Map()["value"].Number() } else { n.ValueNumber = in.Number() } case system.J_BOOL: if in.Type() == system.J_MAP { n.ValueBool = in.Map()["value"].Bool() } else { n.ValueBool = in.Bool() } case system.J_ARRAY: children := in.Array() for i, child := range children { childNode := NewNode() if err := childNode.InitialiseArrayItem(ctx, n, i); err != nil { return kerr.Wrap("XHQKQTNRJV", err) } if err := childNode.AddToArray(ctx, n, i, false); err != nil { return kerr.Wrap("VWWYPDIJKP", err) } if err := childNode.setValue(ctx, child, false); err != nil { return kerr.Wrap("KUCBPFFJNT", err) } } case system.J_MAP: n.Map = map[string]*Node{} children := in.Map() for name, child := range children { childNode := NewNode() if err := childNode.InitialiseMapItem(ctx, n, name); err != nil { return kerr.Wrap("TBNWBMJDIE", err) } if err := childNode.AddToMap(ctx, n, name, false); err != nil { return kerr.Wrap("HTOPDOKPRE", err) } if err := childNode.setValue(ctx, child, false); err != nil { return kerr.Wrap("LWCSAHSBDF", err) } } case system.J_OBJECT: if err := n.initialiseFields(ctx, in, false); err != nil { return kerr.Wrap("XCRYJWKPKP", err) } } return nil }