mapinterface

package module
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2024 License: Apache-2.0 Imports: 5 Imported by: 0

README

mapinterface - A data parser lib for Go with pythonic grammar sugar and as concern as possible for high performance

mapinterface 旨在消灭对map/list解析而产生的层层断言,冗余代码从而提升代码的可读性

快速开始

  1. mapinterface 对map[type]interface{},[]interface进行路径查找,并获取对应的值.

  2. mapinterface Focus的问题: 一个大的json序列为map-interface后, 需要层层断言解析, 导致代码可读性低

  3. mapinterface 期望提供类似于python操作dict的语法糖

  • json.get('key1).get('key2')[1]json['key1']['key2'][1]
  • [get_predict(v) for k,v in dsl['predict']['risk'].iterms() if v['risk_level'] > 20]
  1. 消灭箭头代码

  2. 方便的类型转换,数据过滤功能

安装

$ go get -u github.com/runingriver/mapinterface

调试: replace github.com/runingriver/mapinterface => ../../runingriver/mapinterface

Example

  1. 获取map[string]interface{}中某个key对应的值
jsonStr := '{"name":{"first":"Janet","last":"Prichard"},"age":47}'
var jsonMap map[string]interface{}
_ = json.Unmarshal([]byte(jsonStr), &jsonMap)
// 语法: mapitf.From().Get().GetAny().Index().GetAny().ToStr()
age, err := mapitf.From(jsonMap).Get("name").Get("first").ToStr()
if err != nil {
    return // Get Except return
}
fmt.Println("age:", age) // Janet
  1. 获取map[string]interface{}中某个key对应的值
jsonMap := map[string]interface{}{
    "num": map[int]interface{}{
        1002: []map[string]interface{}{
            {"math": 98},
            {"geography": 88},
        },
    },
}
score, err := mapitf.From(jsonMap).GetAny("num", 1002).Index(0).Get("math").ToInt()
if err != nil {
    return // Get Except return
}
fmt.Println("score:", score) // score = 98 int
  1. 其他操作
// 判断节点是否合法
isValid := mapitf.From(jsonMap).Get("name").Valid()
// 节点是否存在,如果存在返回该节点的值
if v,ok := mapitf.From(jsonMap).Get("name").Exist("first"); ok {
	// do something...
}

注意

  • 日志定义与实现剥离,若希望打印mapitf过程的异常,使用前请先将日志注入
mapitf.Config().SetLogger(logs.DefaultLogger())

进阶

  1. 字符串场景的支持: 默认把所有的Json str当作map[string]interface{}看待.
jsonStr := '{"name":{"first":"Janet","last":"Prichard"},"age":47}'
age, err := mapitf.From(jsonStr).Get("name").Get("first").ToStr()
if err != nil {
    return // Get Except return
}
fmt.Println("age:", age) // string ==> Janet
  1. List Json支持
jsonStr := '[{"first":"Janet","last":"Prichard"},{"first":"Jack","last":"Jam"}]'
age, err := mapitf.From(jsonStr).Index(1).Get("first").ToStr()
if err != nil {
    return // Get Except return
}
fmt.Println("age:", age) // string ==> Jack
  1. ForEach
nameList, err := mapitf.From(mapList[2]).GetAny("users").ForEach(func(i int, k, v interface{}) (key, val interface{}) {
    idNum, cvtErr := mapitf.From(v).Get("id").ToInt64() 
    if cvtErr != nil || idNum <= 1 {
        return nil, nil // 不满足条件,则不加入结果集
    }
    firstName, cvtErr := mapitf.From(v).GetAny("name", "first").ToStr()
    if cvtErr != nil {
        return nil, nil // 不满足条件,则不加入结果集
    }
    return nil, firstName // 结果集为List
}).ToListStrF()
  1. Setter(赋值)
mapJsonStr = map[string]interface{}{
    "str-str": map[string]string{
        "info": "{\"item_id\":7351241250965703963,\"app_id\":\"2324\"}",
    },
}
orgVal, err := mapitf.From(mapJsonStr).SetMap("set-map", "hello world")
orgVal, setErr := mapitf.From(mapJsonStr).Get("str-str").SetAsMap("info")

注:下面的方式也是支持的,但不推荐:

jsonStr := []map[string]interface{}{
    {"first":"Janet","last":"Prichard"},
    {"first":"Jack","last":"Jam"},
}
toMap, err := mapitf.From(jsonStr).Index(1).ToMap()
if err != nil {
    return
}
toMap["age"] = 24
toMap["first"] = "Kite"

原理: mapinterface在层层递进时会hold当前层的value指针,所以可以通过指针进行赋值;

  1. 外传:强大的类型转换
mapStr, err := mapitf.From(val).ToMapStrToStr()
type OjbImpStr struct {
	Name string
	Age  int
}

func (o *OjbImpStr) String() string {
	return fmt.Sprintf("Name:%s,Age:%d", o.Name, o.Age)
}

ois := OjbImpStr{
   Name: "Jack",
   Age:  24,
}

oiStr, err := mapitf.From(ois).ToStr() 
// oiStr: Name:Jack,Age:24
type MockObject int64 // 定义一个类型

mo := MockObject(10)
intStr, err := mapitf.From(mo).ToStr() // 转换为:10
  1. Map内部Json字符串支持
  • 查找时针对map内部val是json字符串的情况,我们也支持像普通map一样进行操作,内部实现原理是:把字符串反转成map再进行相关操作.
    • 注:不会把原来的map从str改成map类型;如果需要请用SetAsMap()
  • ToMap系列,ToList系列的类型转换也支持将json str转成对应的类型;
ListInnerJsonStr = map[string]interface{}{
    "index": "[1,2,3.3,7351241250965703962]",
    "list_map": "[{\"1\":\"2\"}]"
}

// 如下"Index(0)"取json字符串中index为0的内容再对他进行For循环
mapInt, err := mapitf.From(ListInnerJsonStr).Get("list_map").Index(0).ForEach(func(i int, k, v interface{}) (key, val interface{}) {
    return k, v
}).ToMapIntToInt()

listMap, err := mapitf.From(ListInnerJsonStr).Get("list_map").ToListMap() // 此时listMap是一个map对象
  1. 支持ForEach能力(p0), 预案如下: -- v1.0.14已支持
// python => k = [get_predict(v) for k,v in dsl['predict']['risk'].iterms() if v['risk_level'] > 20]

mapitf.From(dsl).Get("predict").Get("risk").ForEach(operationFunc).ToListStr()

operationFunc = func (i int, k, v interface) (key, val interface) {
    if mapitf.From(v).Get('risk_level').ToInt() > 20 {
        return nil, nil
    }
    result := somePkg.getPredict(v)
    return nil, result
}
// python => k = {k:get_predict(v) for k,v in dsl['predict']['risk'].iterms() if v['risk_level'] > 20}

mapitf.From(dsl).Get("predict").Get("risk").ForEach(operationFunc).ToMap()

operationFunc = func (i int, k, v interface) (key, val interface) {
    if mapitf.From(v).Get('risk_level').ToInt() > 20 {
        return nil, nil
    }
    result := somePkg.getPredict(v)
    return k, result
}

规划

  1. 支持条件获取(p2), 预案如下:
// select * from x where (id=1 or id>100) and name rlike "hu%"
mapitf.From().Get().Where("id", eq, 1).OrWhere("id", gt, 100).Where("name", startWith, "hu").ToList()

更新说明

  1. 20240413:重大更新:
    • 支持对对象进行赋值,间Set相关方法
    • 支持ToStruct把结果转成struct
    • ToMap,ToList系列支持将json str转成Map或List
    • 支持非链式调用
    • 整体项目实现优化,删除基础类型map,统一由MapAny承担. 单测从打日志改为assert.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	UniqList = map[string]interface{}{
		"UniqForInt":    []int{1, 1, 2, 2, 3},
		"UniqForIntPtr": []*int{&intPrt, &intPrt2, &intPrt, &intPrt2},
		"UniqForStrItf": []interface{}{"Jak", "Tom", "Kav", "Jak"},
		"UniqForStr":    []string{"Jak", "Tom", "Kav", "Jak"},
		"UniqForObj":    []MockInt{MockInt(1), MockInt(1), MockInt(2), MockInt(2), MockInt(3)},
		"UniqForObjPtr": []*MockInt{&intObjPrt, &intObjPrt2, &intObjPrt, &intObjPrt2},
	}
	CvtMap = map[string]interface{}{
		"StrToStrForStrItf": map[string]interface{}{
			"Kav": "101",
			"Tom": "102",
			"Jak": "103",
		},
		"StrToStrForItfItf": map[interface{}]interface{}{
			&MockObj{"Kav"}: "101",
			&MockObj{"Tom"}: "102",
			&MockObj{"Jak"}: "103",
		},
		"StrToStrForItfObj": map[string]MockObj{
			"101": {"Kav"},
			"102": {"Tom"},
			"103": {"Jak"},
		},
		"IntToIntForStrItf": map[string]interface{}{
			"101": 1,
			"102": 2,
			"103": 3,
		},
		"IntToIntForItfItf": map[interface{}]interface{}{
			"101": MockInt(1),
			"102": MockInt(2),
			"103": MockInt(3),
		},
		"IntToIntForItfObj": map[interface{}]MockInt{
			"101": MockInt(1),
			"102": MockInt(2),
			"103": MockInt(3),
		},
	}
	CvtList = map[string]interface{}{
		"ToListForRf":     []interface{}{&MockObj{"Kav"}, MockObj{"Tom"}, "Jak"},
		"ToListStrForItf": []interface{}{&MockObj{"Kav"}, MockObj{"Tom"}, "Jak"},
		"ToListStrForRf":  []*MockObj{{"Kav"}, {"Tom"}, {"Jak"}},
		"ToListIntForItf": []interface{}{MockInt(101), MockInt(102), MockInt(103)},
		"ToListIntForRf":  []MockInt{101, 102, 103},
	}

	MapAny = map[string]interface{}{
		"map-int-map-str":     mapStrToMap,
		"ptr-map-int-map-str": &mapStrToMap,
		"map-str-ptr": map[string]*struct{ A string }{
			"1": {A: "1"},
			"2": {A: "2"},
		},
		"map-str-map-str": map[string]map[string]string{
			"1": {"a": "b"},
			"2": {"c": "d"},
		},
	}

	OriginTypeChecker = map[string]interface{}{
		"str":       map[string]interface{}{"name": strCase},
		"str-ptr":   map[string]interface{}{"name": &strCase},
		"digit":     map[string]interface{}{"age": digitCase},
		"digit-ptr": map[string]interface{}{"age": &digitCase},
		"list":      []string{"1", "2"},
		"list-str":  &[]string{"2", "3"},
		"list-digit": map[string]interface{}{
			"score": []int32{1, 2, 3},
			"num":   []interface{}{int64(1), int8(2), uint(3), &digitCase},
		},
		"map":         &map[string]interface{}{"name": "Tom"},
		"map-str-itf": map[string]interface{}{"map-str-itf-ptr": &map[string]interface{}{"name": "Tom"}},
	}

	MapInnerJsonStr = `` /* 340-byte string literal not displayed */

	ListInnerJsonStr = `{
		"index": "[1,2,3.3,7351241250965703962]",
		"list_map": "[{\"1\":\"2\"}]"
	}`
	DataCase = `` /* 773-byte string literal not displayed */

	SetAsMap = map[string]interface{}{
		"map-itf-str": map[string]interface{}{
			"coupon_info": "[\n\t{\n\t\t\"coupon_id\": 1792669145841964,\n\t\t\"coupon_discount\": 2000000,\n\t\t\"coupon_remain_discount\": 2000000,\n\t\t\"is_returned\": true\n\t}\n]",
		},
		"map-itf-list-str": map[string]interface{}{
			"coupon_list": []interface{}{"{\"coupon_id\": 1792669145841964}", "7401810649933939467", ""},
		},
		"map-str-str": map[string]interface{}{
			"key": "{\"key1\":\"{\\\"nested_key1\\\":\\\"nested_value1\\\"}\"}",
		},
		"map-str": "{\"key1\":\"{\\\"nested_key1\\\":\\\"nested_value1\\\"}\"}",
		"map-type-except": map[string]string{
			"key": "{\"nested_key1\":\"nested_value1\"}",
		},
		"map-itf-list-except": map[string]interface{}{
			"coupon_list": []string{"{\"coupon_id\": 1792669145841964}", "7401810649933939467", ""},
		},
	}
)

Functions

func JsonToMap

func JsonToMap() (mapStrItf []map[string]interface{}, err error)

func ListJson

func ListJson() ([]interface{}, error)

Types

type MockInt added in v1.2.1

type MockInt int64

type MockObj added in v1.2.1

type MockObj struct {
	Name string
}

func (*MockObj) String added in v1.2.1

func (m *MockObj) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL