All Projects → liip → Sheriff

liip / Sheriff

Licence: bsd-3-clause
Conditional marshalling for Go

Programming Languages

go
31211 projects - #10 most used programming language
golang
3204 projects
reflection
70 projects

Labels

Projects that are alternatives of or similar to Sheriff

Xresloader
跨平台Excel导表工具(Excel=>protobuf/msgpack/lua/javascript/json/xml)
Stars: ✭ 161 (-3.59%)
Mutual labels:  json
Jackson Datatype Money
Extension module to properly support datatypes of javax.money
Stars: ✭ 165 (-1.2%)
Mutual labels:  json
Models
WordPress plugin to create custom post types and taxonomies using JSON, YAML or PHP files
Stars: ✭ 167 (+0%)
Mutual labels:  json
Api Diff
A command line tool for diffing json rest APIs
Stars: ✭ 164 (-1.8%)
Mutual labels:  json
Go Rejson
Golang client for redislabs' ReJSON module with support for multilple redis clients (redigo, go-redis)
Stars: ✭ 164 (-1.8%)
Mutual labels:  json
Js Yaml Front Matter
Parses yaml or json from the beginning of a string or file
Stars: ✭ 165 (-1.2%)
Mutual labels:  json
Goat
[DEPRECATED] 🐐 A minimalistic JSON API server in Go
Stars: ✭ 161 (-3.59%)
Mutual labels:  json
Lite Editor
A Modern WYSIWYG Editor especially for inline elements
Stars: ✭ 169 (+1.2%)
Mutual labels:  json
Thememanager
ThemeManager is a lightweight library for application to switching themes. support more attributes and theme extensions. more easy and convenient to use.
Stars: ✭ 165 (-1.2%)
Mutual labels:  json
Gojay
fastest JSON encoder/decoder with powerful stream API for Golang
Stars: ✭ 2,009 (+1102.99%)
Mutual labels:  json
Jackson Core
Core part of Jackson that defines Streaming API as well as basic shared abstractions
Stars: ✭ 2,003 (+1099.4%)
Mutual labels:  json
Go Jsonschema
A tool to generate Go data types from JSON Schema definitions.
Stars: ✭ 164 (-1.8%)
Mutual labels:  json
Aspjson
A fast classic ASP JSON parser and encoder for easy JSON manipulation to work with the new JavaScript MV* libraries and frameworks.
Stars: ✭ 165 (-1.2%)
Mutual labels:  json
Dop
JavaScript implementation for Distributed Object Protocol
Stars: ✭ 163 (-2.4%)
Mutual labels:  json
Newtonsoft.json.schema
Json.NET Schema is a powerful, complete and easy to use JSON Schema framework for .NET
Stars: ✭ 167 (+0%)
Mutual labels:  json
Open Sketch
[deprecated] Change the design work. Version control for design file.
Stars: ✭ 162 (-2.99%)
Mutual labels:  json
Simple Settings
A simple way to manage your project settings.
Stars: ✭ 165 (-1.2%)
Mutual labels:  json
Related
Nested Object Models in Python with dictionary, YAML, and JSON transformation support
Stars: ✭ 169 (+1.2%)
Mutual labels:  json
Csvreader
csvreader library / gem - read tabular data in the comma-separated values (csv) format the right way (uses best practices out-of-the-box with zero-configuration)
Stars: ✭ 169 (+1.2%)
Mutual labels:  json
React Json View
JSON viewer for react
Stars: ✭ 2,356 (+1310.78%)
Mutual labels:  json

sheriff

GoDoc Build Status Coverage Status

go get github.com/liip/sheriff

Package sheriff marshals structs conditionally based on tags on the fields.

A typical use is an API which marshals structs into JSON and maintains different API versions. Using sheriff, struct fields can be annotated with API version and group tags.

By invoking sheriff with specific options, those tags determine whether a field will be added to the output map or not. It can then be marshalled using "encoding/json".

NOTE: This package is tested only on Go 1.7+, it might work on Go 1.6 too, but no support is given.

Implemented tags

Groups

Groups can be used for limiting the output based on freely defined parameters. For example: restrict marshalling the email address of a user to the user itself by just adding the group personal if the user fetches his profile. Multiple groups can be separated by comma.

Example:

type GroupsExample struct {
    Username      string `json:"username" groups:"api"`
    Email         string `json:"email" groups:"personal"`
    SomethingElse string `json:"something_else" groups:"api,personal"`
}

Anonymous fields

Tags added to a struct’s anonymous field propagates to the inner-fields if no other tags are specified.

Example:

type UserInfo struct {
    UserPrivateInfo `groups:"private"`
    UserPublicInfo  `groups:"public"`
}
type UserPrivateInfo struct {
    Age string
}
type UserPublicInfo struct {
    ID    string
    Email string
}

Since

Since specifies the version since that field is available. It's inclusive and SemVer compatible using github.com/hashicorp/go-version. If you specify version 2 in a tag, this version will be output in case you specify version >=2.0.0 as the API version.

Example:

type SinceExample struct {
    Username string `json:"username" since:"2.1.0"`
    Email    string `json:"email" since:"2"`
}

Until

Until specifies the version until that field is available. It's the opposite of since, inclusive and SemVer compatible using github.com/hashicorp/go-version. If you specify version 2 in a tag, this version will be output in case you specify version <=2.0.0 as the API version.

Example:

type UntilExample struct {
    Username string `json:"username" until:"2.1.0"`
    Email    string `json:"email" until:"2"`
}

Example

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/hashicorp/go-version"
	"github.com/liip/sheriff"
)

type User struct {
	Username string   `json:"username" groups:"api"`
	Email    string   `json:"email" groups:"personal"`
	Name     string   `json:"name" groups:"api"`
	Roles    []string `json:"roles" groups:"api" since:"2"`
}

type UserList []User

func MarshalUsers(version *version.Version, groups []string, users UserList) ([]byte, error) {
	o := &sheriff.Options{
		Groups:     groups,
		ApiVersion: version,
	}

	data, err := sheriff.Marshal(o, users)
	if err != nil {
		return nil, err
	}

	return json.MarshalIndent(data, "", "  ")
}

func main() {
	users := UserList{
		User{
			Username: "alice",
			Email:    "[email protected]",
			Name:     "Alice",
			Roles:    []string{"user", "admin"},
		},
		User{
			Username: "bob",
			Email:    "[email protected]",
			Name:     "Bob",
			Roles:    []string{"user"},
		},
	}

	v1, err := version.NewVersion("1.0.0")
	if err != nil {
		log.Panic(err)
	}
	v2, err := version.NewVersion("2.0.0")

	output, err := MarshalUsers(v1, []string{"api"}, users)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println("Version 1 output:")
	fmt.Printf("%s\n\n", output)

	output, err = MarshalUsers(v2, []string{"api"}, users)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println("Version 2 output:")
	fmt.Printf("%s\n\n", output)

	output, err = MarshalUsers(v2, []string{"api", "personal"}, users)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println("Version 2 output with personal group too:")
	fmt.Printf("%s\n\n", output)

}

// Output:
// Version 1 output:
// [
//   {
//     "name": "Alice",
//     "username": "alice"
//   },
//   {
//     "name": "Bob",
//     "username": "bob"
//   }
// ]
//
// Version 2 output:
// [
//   {
//     "name": "Alice",
//     "roles": [
//       "user",
//       "admin"
//     ],
//     "username": "alice"
//   },
//   {
//     "name": "Bob",
//     "roles": [
//       "user"
//     ],
//     "username": "bob"
//   }
// ]
//
// Version 2 output with personal group too:
// [
//   {
//     "email": "[email protected]",
//     "name": "Alice",
//     "roles": [
//       "user",
//       "admin"
//     ],
//     "username": "alice"
//   },
//   {
//     "email": "[email protected]",
//     "name": "Bob",
//     "roles": [
//       "user"
//     ],
//     "username": "bob"
//   }
// ]

Benchmarks

There's a simple benchmark in bench_test.go which compares running sheriff -> JSON versus just marshalling into JSON and runs on every build. Just marshalling JSON itself takes usually between 3 and 5 times less nanoseconds per operation compared to running sheriff and JSON.

Want to make sheriff faster? Please send us your pull request or open an issue discussing a possible improvement 🚀!

Acknowledgements

  • This idea and code has been created partially during a Liip hackday.
  • Thanks to @basgys for reviews & improvements.

Related projects

mweibel/php-to-go is a code generator translating PHP models (using JMS serializer) to Go structs with sheriff tags. The two projects were initially developed together and just recently php-to-go has been split out and published too.

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].