All Projects → iFaceless → portal

iFaceless / portal

Licence: MIT license
A lightweight framework for golang object (struct) serialization (mapping). Inspired heavily by marshmallow (a Python library).

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to portal

rust-concurrency-patterns
Examples of concurrency patterns implemented in Rust
Stars: ✭ 29 (+20.83%)
Mutual labels:  concurrency
ComposableAsync
Create, compose and inject asynchronous behaviors in .Net Framework and .Net Core.
Stars: ✭ 28 (+16.67%)
Mutual labels:  concurrency
cl-gserver
Actor framework featuring actors and agents for easy access to state and asynchronous operations.
Stars: ✭ 121 (+404.17%)
Mutual labels:  concurrency
gateCracker
No description or website provided.
Stars: ✭ 20 (-16.67%)
Mutual labels:  restful-api
practice
Java并发编程与高并发解决方案:http://coding.imooc.com/class/195.html Java开发企业级权限管理系统:http://coding.imooc.com/class/149.html
Stars: ✭ 39 (+62.5%)
Mutual labels:  concurrency
restful-services-in-pyramid
RESTful / HTTP services in Pyramid and Python course handout materials
Stars: ✭ 56 (+133.33%)
Mutual labels:  restful-api
AnomalyDetection
基于智能计算框架nupic的异常检测restful Api.
Stars: ✭ 31 (+29.17%)
Mutual labels:  restful-api
api
DotKernel's PSR-7 REST style API built around the Mezzio API skeleton.
Stars: ✭ 16 (-33.33%)
Mutual labels:  restful-api
idle
Idle is an asynchronous and hot-reloadable C++ dynamic component framework
Stars: ✭ 169 (+604.17%)
Mutual labels:  concurrency
ratelimiter
A concurrent rate limiter library for Golang based on Sliding-Window rate limiter algorithm.
Stars: ✭ 218 (+808.33%)
Mutual labels:  concurrency
egg-RESTfulAPI
基于egg.js2.x的RESTfulAPI风格的项目模板,用于快速构建高性能的服务端。
Stars: ✭ 70 (+191.67%)
Mutual labels:  restful-api
Mangadb
A Secured RESTful API Service for Manga
Stars: ✭ 17 (-29.17%)
Mutual labels:  restful-api
pinboard
A threadsafe way to publish data, just stick it on the pinboard
Stars: ✭ 24 (+0%)
Mutual labels:  concurrency
ogen
OpenAPI v3 code generator for go
Stars: ✭ 436 (+1716.67%)
Mutual labels:  restful-api
gcl
A graph concurrent library for C++
Stars: ✭ 21 (-12.5%)
Mutual labels:  concurrency
go-onion-architecture-sample
Sample RestAPI project write in Go
Stars: ✭ 40 (+66.67%)
Mutual labels:  restful-api
rest.vertx
A JAX-RS like annotation processor for vert.x verticals and more
Stars: ✭ 138 (+475%)
Mutual labels:  restful-api
angular6-httpclient-example
Angular 6 HttpClient: Consume RESTful API Example
Stars: ✭ 38 (+58.33%)
Mutual labels:  restful-api
metalarchives-api
RESTful API for metal-archives.com
Stars: ✭ 26 (+8.33%)
Mutual labels:  restful-api
feedpushr
A simple feed aggregator daemon with sugar on top.
Stars: ✭ 222 (+825%)
Mutual labels:  restful-api

Build Status Coverage Status Go Report Card

戳我看中文介绍

What's portal?

portal game

It's a lightweight package which simplifies Go object serialization. Inspired by marshmallow, but with concurrency builtin for better performance.

portal can be used to serialize app-level objects to specified objects (schema structs). The serialized objects can be rendered to any standard formats like JSON for an HTTP API. Most importantly, if some fields of a schema have different data sources, portal could spawn several goroutines to retrieve fields' data concurrently.

Note that unlike marshmallow, portal only focuses on object serialization. So, if you want to validate struct fields, please refer to go-playground/validator or asaskevich/govalidator.

Features

  1. Can be configured to fill data into multiple fields concurrently.
  2. Support flexible field filtering for any (nested) schemas.
  3. Automatically convert field data to the expected field type, no more boilerplate code.
  4. Simple and clean API.

Install

get get -u github.com/ifaceless/portal

Quickstart

Full example can be found here.

Model Definitions

CLICK HERE | model.go
type NotificationModel struct {
	ID      int
	Title   string
	Content string
}

type UserModel struct {
	ID int
}

func (u *UserModel) Fullname() string {
	return fmt.Sprintf("user:%d", u.ID)
}

func (u *UserModel) Notifications() (result []*NotificationModel) {
	for i := 0; i < 1; i++ {
		result = append(result, &NotificationModel{
			ID:      i,
			Title:   fmt.Sprintf("title_%d", i),
			Content: fmt.Sprintf("content_%d", i),
		})
	}
	return
}

type TaskModel struct {
	ID     int
	UserID int
	Title  string
}

func (t *TaskModel) User() *UserModel {
	return &UserModel{t.UserID}
}

Schema Definitions

CLICK HERE | schema.go
type NotiSchema struct {
	ID      string `json:"id,omitempty"`
	Title   string `json:"title,omitempty"`
	Content string `json:"content,omitempty"`
}

type UserSchema struct {
	ID                   string        `json:"id,omitempty"`
	// Get user name from `UserModel.Fullname()`
	Name                 string        `json:"name,omitempty" portal:"attr:Fullname"`
	Notifications        []*NotiSchema `json:"notifications,omitempty" portal:"nested"`
	AnotherNotifications []*NotiSchema `json:"another_notifications,omitempty" portal:"nested;attr:Notifications"`
}

type TaskSchema struct {
	ID          string      `json:"id,omitempty"`
	Title       string      `json:"title,omitempty"`
	Description string      `json:"description,omitempty" portal:"meth:GetDescription"`
	// UserSchema is a nested schema
	User        *UserSchema `json:"user,omitempty" portal:"nested"`
	// We just want `Name` field for `SimpleUser`.
	// Besides, the data source is the same with `UserSchema`
	SimpleUser  *UserSchema `json:"simple_user,omitempty" portal:"nested;only:Name;attr:User"`
}

func (ts *TaskSchema) GetDescription(model *model.TaskModel) string {
	return "Custom description"
}

Serialization Examples

package main

import (
	"encoding/json"
	"github.com/ifaceless/portal"
)

func main() {
	// log debug info
	portal.SetDebug(true)
	// set max worker pool size
	portal.SetMaxPoolSize(1024)
	// make sure to clean up.
	defer portal.CleanUp()

	// write to a specified task schema
	var taskSchema schema.TaskSchema
	portal.Dump(&taskSchema, &taskModel)
	// data: {"id":"1","title":"Finish your jobs.","description":"Custom description","user":{"id":"1","name":"user:1","notifications":[{"id":"0","title":"title_0","content":"content_0"}],"another_notifications":[{"id":"0","title":"title_0","content":"content_0"}]},"simple_user":{"name":"user:1"}}
	data, _ := json.Marshal(taskSchema)

	// select specified fields
	portal.Dump(&taskSchema, &taskModel, portal.Only("Title", "SimpleUser"))
	// data: {"title":"Finish your jobs.","simple_user":{"name":"user:1"}}
	data, _ := json.Marshal(taskSchema)
	
	// select fields with alias defined in the json tag.
	// actually, the default alias tag is `json`, `portal.FieldAliasMapTagName("json")` is optional.
	portal.Dump(&taskSchema, &taskModel, portal.Only("title", "SimpleUser"), portal.FieldAliasMapTagName("json"))
	// data: {"title":"Finish your jobs.","simple_user":{"name":"user:1"}}
	data, _ := json.Marshal(taskSchema)

	// you can keep any fields for any nested schemas
	// multiple fields are separated with ','
	// nested fields are wrapped with '[' and ']'
	portal.Dump(&taskSchema, &taskModel, portal.Only("ID", "User[ID,Notifications[ID],AnotherNotifications[Title]]", "SimpleUser"))
	// data: {"id":"1","user":{"id":"1","notifications":[{"id":"0"}],"another_notifications":[{"title":"title_0"}]},"simple_user":{"name":"user:1"}}
	data, _ := json.Marshal(taskSchema)

	// ignore specified fields
	portal.Dump(&taskSchema, &taskModel, portal.Exclude("Description", "ID", "User[Name,Notifications[ID,Content],AnotherNotifications], SimpleUser"))
	// data: {"title":"Finish your jobs.","user":{"id":"1","notifications":[{"title":"title_0"}]}}
	data, _ := json.Marshal(taskSchema)

	// dump multiple tasks
	var taskSchemas []schema.TaskSchema
	portal.Dump(&taskSchemas, &taskModels, portal.Only("ID", "Title", "User[Name]"))
	// data: [{"id":"0","title":"Task #1","user":{"name":"user:100"}},{"id":"1","title":"Task #2","user":{"name":"user:101"}}]
	data, _ := json.Marshal(taskSchema)
}

To learn more about portal, please read the User Guide~

Concurrency Strategy

  1. Any fields tagged with portal:"async" will be serialized asynchronously.
  2. When dumping to multiple schemas, portal will do it concurrently if any fields in the schema are tagged with protal:"async".
  3. You can always disable concurrency strategy with option portal.DisableConcurrency().

Cache Strategy

  1. Cache is implemented in the field level when portal.SetCache(portal.DefaultCache) is configured.
  2. Cache will be disabled by tagging the fields with portal:"disablecache" or by defining a PortalDisableCache() bool meth for the schema struct, or by a portal.DisableCache() option setting while dumping.
  3. Cache is available for one schema's one time dump, after the dump, the cache will be invalidated.

Core APIs

func New(opts ...Option) (*Chell, error)
func Dump(dst, src interface{}, opts ...Option) error 
func DumpWithContext(ctx context.Context, dst, src interface{}, opts ...Option)
func SetDebug(v bool)
func SetLogLevel(level LogLevel)
func SetMaxPoolSize(size int)
func CleanUp()

More Field Types

  • field.Timestamp: time.Time <-> unix timestamp.
  • field.UpperString: convert string to upper case.
  • field.LowerString: convert string to lower case.

License

portal is licensed under the MIT license. Please feel free and have fun~

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].