为了账号安全,请及时绑定邮箱和手机立即绑定

仅解组已批准的字段

仅解组已批准的字段

Go
FFIVE 2022-06-01 16:10:10
我正在尝试授予用户编辑结构的某些字段的权限。此字段将根据当前用户的操作、上下文和角色而有所不同。目前我正在以一种命令式的方式执行此操作,但它相当乏味且不可扩展。我认为拥有一个列表approved_fields可能是一个很好且更具可扩展性的解决方案,但我不知道如何完成这个。我认为反思是要走的路,但我还不够了解。任何灵感都会有所帮助。type Foo struct {  Bar1 int  Bar2 int  Bar3 int}foo := Foo{}approved_fields := []string{"Bar1", "Bar2"}decode(json_data, &foo, approved_fields)foo2 := Foo{}approved_fields := []string{"Bar1", "Bar3"}decode(json_data, &foo2, approved_fields)
查看完整描述

1 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

这是我如何解决它的想法。由于我在有选择地选择字段之前解组了整个项目,因此可能会有更有效的方法。


import (

    "encoding/json"

    "log"

    "reflect"


    "github.com/pkg/errors"

)


func fieldByName(s string, v interface{}) (reflect.Value, error) {

    el := reflect.ValueOf(v).Elem()

    fbn := el.FieldByName(s)

    if !fbn.IsValid() {

        return fbn, errors.Errorf("does not have field named %s", s)

    }

    return fbn, nil

}


func decode(data []byte, v interface{}, approvedFields []string) error {

    typeOf := reflect.TypeOf(v)

    if typeOf.Kind() == reflect.Ptr {

        typeOf = typeOf.Elem()

    }

    if typeOf.Kind() == reflect.Slice {

        return errors.New("does not support slices")

    }


    newItem := reflect.New(typeOf)

    newItemInterface := newItem.Interface()

    if err := json.Unmarshal(data, &newItemInterface); err != nil {

        return errors.Wrap(err, "json unmarshall")

    }

    for _, approvedField := range approvedFields {

        fbn, err := fieldByName(approvedField, v)

        if err != nil {

            return errors.Wrap(err, "field by name")

        }

        val, _ := fieldByName(approvedField, newItemInterface)

        fbn.Set(val)

    }

    return nil

}

一个测试:


func TestBar1Bar2(t *testing.T) {

    var json_data []byte

    {

        f := &Foo{

            Bar1: 1,

            Bar2: 2,

            Bar3: 3,

        }

        json_data, _ = json.Marshal(f)

    }

    approved_fields := []string{"Bar1", "Bar2"}

    f := &Foo{}

    err := decode(json_data, f, approved_fields)

    if err != nil {

        t.Fatal(err)

    }

    assert.Equal(t, f.Bar1, 1)

    assert.Equal(t, f.Bar2, 2)

    assert.Equal(t, f.Bar3, 0)

}


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 87 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号