Skip to content
Snippets Groups Projects
Commit 0baa3151 authored by Danis Kirasirov's avatar Danis Kirasirov
Browse files

wip

parent 93fdc42e
No related branches found
No related tags found
No related merge requests found
......@@ -293,11 +293,11 @@ func (i *Item) Encode(ctx context.Context, s *schema.Schema) (*Item, error) {
return &res, nil
}
func (i *Item) Decode(ctx context.Context, s *schema.Schema) (*Item, error) {
func (i *Item) Decode(ctx context.Context, s *schema.Schema, opts ...field.EncodeOption) (*Item, error) {
res := *i
var err error
if i.Data != nil {
res.Data, err = s.Decode(ctx, i.Data)
res.Data, err = s.Decode(ctx, i.Data, opts...)
if err != nil {
return nil, err
}
......@@ -309,7 +309,7 @@ func (i *Item) Decode(ctx context.Context, s *schema.Schema) (*Item, error) {
res.Translations[l] = v
continue
}
dt, err := schema.Decode(ctx, s, v)
dt, err := schema.Decode(ctx, s, v, opts...)
if err != nil {
return nil, err
}
......
......@@ -120,6 +120,19 @@ func (ArrayType) IsEmpty(v interface{}) bool {
// return nil
//}
func (ArrayType) NonStrictConverter(_ context.Context, _ *Field, v interface{}) interface{} {
if v == nil {
return nil
}
// Если в данных хранится не слайс или массив, преобразуем в слайс из одного элемента
if arr := reflect.ValueOf(v); arr.Kind() != reflect.Slice && arr.Kind() != reflect.Array {
return []interface{}{v}
}
return v
}
func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkFunc, opts *WalkOptions) (interface{}, bool, error) {
var changed bool
params, ok := field.Params.(*ArrayParameters)
......
......@@ -14,18 +14,42 @@ type Encoder interface {
Encode(ctx context.Context, field *Field, v interface{}) (interface{}, error)
}
func Decode(ctx context.Context, w Walker, v interface{}) (interface{}, error) {
var err error
//if ctx == nil {
// ctx = NewContext()
//}
//
//if m, ok := v.(map[string]interface{}); ok {
// ctx = ctx.ExtendEnv(m)
// ctx.DisableConditions = true
//}
// NonStrictConverter определяет метод для преобразования данных в нестрогом режиме.
type NonStrictConverter interface {
NonStrictConverter(ctx context.Context, field *Field, v interface{}) interface{}
}
type EncodeOptions struct {
NonStrictMode bool
}
type EncodeOption func(opts *EncodeOptions)
// NonStrictMode указывает, что декодирование необходимо провести в нестрогом режиме.
func NonStrictMode() EncodeOption {
return func(opts *EncodeOptions) {
opts.NonStrictMode = true
}
}
func NewEncodeOptions(opt ...EncodeOption) *EncodeOptions {
opts := &EncodeOptions{}
for _, o := range opt {
o(opts)
}
return opts
}
func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption) (interface{}, error) {
opt := NewEncodeOptions(opts...)
val, _, err := w.Walk(ctx, v, func(ctx context.Context, f *Field, v interface{}) (res WalkFuncResult, err error) {
if opt.NonStrictMode {
if converter, ok := f.GetType().(NonStrictConverter); ok {
v = converter.NonStrictConverter(ctx, f, v)
}
}
if decoder, ok := f.GetType().(Decoder); ok {
if v, err = decoder.Decode(ctx, f, v); err != nil {
return
......
......@@ -4,6 +4,7 @@ import (
"context"
"math"
"reflect"
"strconv"
"github.com/pkg/errors"
)
......@@ -138,6 +139,25 @@ func (n NumberType) Encode(ctx context.Context, field *Field, v interface{}) (in
return n.decode(ctx, field, v)
}
func (NumberType) NonStrictConverter(_ context.Context, _ *Field, v interface{}) interface{} {
if v == nil {
return nil
}
// Если строка, пробуем преобразовать в число
if s, ok := v.(string); ok {
if i, err := strconv.ParseInt(s, 0, 64); err == nil {
return i
}
if f, err := strconv.ParseFloat(s, 64); err == nil {
return f
}
}
return v
}
func Number(format string, o ...interface{}) *Field {
return NewField(&NumberParameters{Format: format}, o...)
}
......@@ -58,6 +58,17 @@ func (StringType) Encode(_ context.Context, _ *Field, v interface{}) (interface{
return nil, fmt.Errorf("StringField encode error: unsupported value type : \"%s\"", reflect.ValueOf(v).Kind())
}
func (StringType) NonStrictConverter(_ context.Context, _ *Field, v interface{}) interface{} {
if v == nil {
return nil
}
if _, ok := v.(string); ok {
return v
}
return fmt.Sprintf("%v", v)
}
func String(o ...interface{}) *Field {
return NewField(&StringParameters{}, o...)
}
......@@ -148,16 +148,17 @@ func (s *Schema) Evaluate(ctx context.Context, data map[string]interface{}) (res
return
}
func (s *Schema) Decode(ctx context.Context, v interface{}) (res map[string]interface{}, err error) {
if err = s.Load(ctx); err != nil {
func (s *Schema) Decode(ctx context.Context, v interface{}, opt ...field.EncodeOption) (map[string]interface{}, error) {
if err := s.Load(ctx); err != nil {
return nil, err
}
if v, err = Decode(ctx, s, v); err != nil {
v, err := Decode(ctx, s, v, opt...)
if err != nil {
return nil, err
}
res, _ = v.(map[string]interface{})
return
res, _ := v.(map[string]interface{})
return res, err
}
func (s *Schema) Encode(ctx context.Context, v interface{}) (interface{}, error) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment