Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

github.com/perimeterx/marshmallow

Package Overview
Dependencies
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github.com/perimeterx/marshmallow

  • v1.1.5
  • Source
  • Go
  • Socket score

Version published
Created
Source

Marshmallow

Marshmallow Campfire

CodeQL Status Run Tests Dependency Review Go Report Card Manual Code Coverage Go Reference Licence Latest Release Top Languages Issues Pull Requests Commits Contributor Covenant

marshmallow-gopher

Marshmallow package provides a simple API to perform flexible and performant JSON unmarshalling in Go.

Marshmallow specializes in dealing with unstructured struct - when some fields are known and some aren't, with zero performance overhead nor extra coding needed. While unmarshalling, marshmallow allows fully retaining the original data and access it via a typed struct and a dynamic map.

Contents

Install

go get -u github.com/perimeterx/marshmallow

Usage

package main

import (
	"fmt"
	"github.com/perimeterx/marshmallow"
)

func main() {
	v := struct {
		Foo string `json:"foo"`
		Boo []int  `json:"boo"`
	}{}
	result, err := marshmallow.Unmarshal([]byte(`{"foo":"bar","boo":[1,2,3],"goo":12.6}`), &v)
	fmt.Printf("v=%+v, result=%+v, err=%v", v, result, err)
	// Output: v={Foo:bar Boo:[1 2 3]}, result=map[boo:[1 2 3] foo:bar goo:12.6], err=<nil>
}

Examples can be found here

Performance Benchmark And Alternatives

Marshmallow performs best when dealing with mixed data - when some fields are known and some are unknown. More info below. Other solutions are available for this kind of use case, each solution is explained and documented in the link below. The full benchmark test can be found here.

BenchmarkIterationsTime/IterationBytes AllocatedAllocations
unmarshall twice2286935164 ns/op1640 B/op51 allocs/op
raw map2322365116 ns/op2296 B/op53 allocs/op
go codec3884423077 ns/op2512 B/op37 allocs/op
marshmallow6261681853 ns/op608 B/op18 allocs/op
marshmallow without populating struct6786161751 ns/op608 B/op18 allocs/op

marshmallow performance comparison

Marshmallow provides the best performance (up to X3 faster) while not requiring any extra coding. In fact, marshmallow performs as fast as normal json.Unmarshal call, however, such a call causes loss of data for all the fields that did not match the given struct. With marshmallow you never lose any data.

BenchmarkIterationsTime/IterationBytes AllocatedAllocations
marshmallow6261681853 ns/op608 B/op18 allocs/op
native library6521061845 ns/op304 B/op11 allocs/op
marshmallow without populating struct6786161751 ns/op608 B/op18 allocs/op

When Should I Use Marshmallow

Marshmallow is best suited for use cases where you are interested in all the input data, but you have predetermined information only about a subset of it. For instance, if you plan to reference two specific fields from the data, then iterate all the data and apply some generic logic. How does it look with the native library:

func isAllowedToDrive(data []byte) (bool, error) {
	result := make(map[string]interface{})
	err := json.Unmarshal(data, &result)
	if err != nil {
		return false, err
	}

	age, ok := result["age"]
	if !ok {
		return false, nil
	}
	a, ok := age.(float64)
	if !ok {
		return false, nil
	}
	if a < 17 {
		return false, nil
	}

	hasDriversLicense, ok := result["has_drivers_license"]
	if !ok {
		return false, nil
	}
	h, ok := hasDriversLicense.(bool)
	if !ok {
		return false, nil
	}
	if !h {
		return false, nil
	}

	for key := range result {
		if strings.Contains(key, "prior_conviction") {
			return false, nil
		}
	}

	return true, nil
}

And with marshmallow:

func isAllowedToDrive(data []byte) (bool, error) {
	v := struct {
		Age               int  `json:"age"`
		HasDriversLicense bool `json:"has_drivers_license"`
	}{}
	result, err := marshmallow.Unmarshal(data, &v)
	if err != nil {
		return false, err
	}

	if v.Age < 17 || !v.HasDriversLicense {
		return false, nil
	}

	for key := range result {
		if strings.Contains(key, "prior_conviction") {
			return false, nil
		}
	}

	return true, nil
}

API

Marshmallow exposes two main API functions - Unmarshal and UnmarshalFromJSONMap. While unmarshalling, marshmallow supports the following optional options:

In order to capture unknown nested fields, structs must implement JSONDataErrorHandler. More info here.

Marshmallow also supports caching of refection information using EnableCache and EnableCustomCache.

Contact and Contribute

Reporting issues and requesting features may be done in our GitHub issues page. Discussions may be conducted in our GitHub discussions page. For any further questions or comments you can reach us out at open-source@humansecurity.com.

Any type of contribution is warmly welcome and appreciated ❤️ Please read our contribution guide for more info.

If you're looking for something to get started with, tou can always follow our issues page and look for good first issue and help wanted labels.

Marshmallow logo and assets by Adva Rom are licensed under a Creative Commons Attribution 4.0 International License.

Marshmallow Logo

FAQs

Package last updated on 03 Jul 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc