jsmu

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2022 License: MIT Imports: 6 Imported by: 0

README

Go Reference Go Report Card Build Status codecov

jsmu aka JavaScript Marshal|Unmarshal. Pronounce as j◦s◦mew.

jsmu.MU

jsmu.MU abstracts the typical 2-pass JSON marshal|unmarshal into a single pass.

Create an instance of jsmu.MU:

mu := &jsmu.MU{}

Register types that will be JSON marshalled or unmarshalled:

mu.Register( &SomeType{} )
mu.Register( &OtherType{} )

To unmarshal:

var envelope jsmu.Enveloper
var err error
for data := range jsonCh { // jsonCh is some stream returning blobs of JSON
    if envelope, err = mu.Unmarshal([]byte(data)); err != nil {
        // YOUSHOULD Handle err.
        continue // break, goto, return, etc.
    }
    switch message := envelope.GetMessage().(type) {
        case *SomeType:
        case *OtherType:
    }
}

To marshal:

var buf []byte
var err error
some, other := &SomeType{}, &OtherType{}
if buf, err = mu.Marshal(some); err != nil {
    // YOUSHOULD Handle err.
}
// YOUSHOULD Do something with buf.
if buf, err = mu.Marshal(other); err != nil {
    // YOUSHOULD Handle err
}
// YOUSHOULD Do something with buf.

Envelopes

jsmu expects JSON encoded data to be wrapped inside an envelope. This envelope must contain some type name information (data type string) and the message payload. The default envelope structure is:

{
    // string, required : Must uniquely identify the contents of "message".
    "type"    : "",
    // string, optional : Provided as a convenience for round trip message flow.
    "id"      : "",
    // The data.
    "message" : any
}

Envelopes are created by the EnveloperFn member of jsmu.MU; if you don't provide a value for EnveloperFn then jsmu.DefaultEnveloperFunc is used and JSON is expected to conform to the above structure.

If you want to use a different JSON structure you can implement the jsmu.Enveloper interface and provide an appropriate EnveloperFn value when instantiating your jsmu.MU; see example MU (CustomEnvelope).

The Dual Nature of MU.Marshal()

MU.Marshal() always returns JSON representing a message within an envelope.

  • Calling MU.Marshal(value) when value is already a jsmu.Enveloper yields:

    1. value is marshalled as-is.
  • Calling MU.Marshal(value) when value is not a jsmu.Enveloper yields:

    1. A new envelope is created with MU.EnveloperFn.
    2. value is placed in the envelope.
    3. The newly created envelope is marshalled.

Performance

jsmu.MU has not yet been optimized. However the extra overhead is not much slower than handling 2-pass JSON directly in your application (at least for the simple test I put together):

goos: windows
goarch: amd64
pkg: github.com/nofeaturesonlybugs/jsmu
cpu: Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
BenchmarkMU/2-pass_unmarshal_limit_5-8             52425             23602 ns/op            7488 B/op        140 allocs/op
BenchmarkMU/jsmu_unmarshal_limit_5-8               50223             24460 ns/op            7008 B/op        130 allocs/op
BenchmarkMU/2-pass_unmarshal_limit_100-8            2731            466576 ns/op          147256 B/op       2800 allocs/op
BenchmarkMU/jsmu_unmarshal_limit_100-8              2668            476442 ns/op          137656 B/op       2600 allocs/op
BenchmarkMU/2-pass_unmarshal_limit_250-8             994           1171133 ns/op          367593 B/op       7000 allocs/op
BenchmarkMU/jsmu_unmarshal_limit_250-8              1014           1194731 ns/op          343593 B/op       6500 allocs/op
BenchmarkMU/2-pass_unmarshal_limit_500-8             519           2343670 ns/op          734043 B/op      14000 allocs/op
BenchmarkMU/jsmu_unmarshal_limit_500-8               513           2394790 ns/op          686043 B/op      13000 allocs/op
BenchmarkMU/2-pass_unmarshal_limit_1000-8            255           4734993 ns/op         1467949 B/op      28000 allocs/op
BenchmarkMU/jsmu_unmarshal_limit_1000-8              244           4788199 ns/op         1371949 B/op      26000 allocs/op
PASS
ok      github.com/nofeaturesonlybugs/jsmu      14.532s

Documentation

Overview

Package jsmu abstracts the typical 2-pass JSON encoding into what looks like a 1-pass JSON encoding step when marshalling or unmarshalling data.

Pronounce as j◦s◦mew.

TypeName, ConcreteType, and 2-Pass Encoding

Writing a general purpose JSON unmarshaller usually requires the following steps:

  1. json.Unmarshal() into a type containing at least two fields: a. int|string field identifying the desired Go struct destination type; call this the TypeName field. b. json.RawMessage field containing the data or payload that is not yet unmarshalled.
  2. Type switch or branch off the TypeName field to create a Go struct destination; call this the ConcreteType
  3. json.Unmarshal() the json.RawMessage into ConcreteType.

Writing a general purpose JSON marshaller works in reverse:

  1. json.Marshal() the outgoing ConcreteType to json.RawMessage.
  2. Type switch or branch off the outgoing ConcreteType to create an int|string TypeName identification.
  3. Pack the outputs from steps 1 and 2 (along with any other desired information) into some type of envelope and json.Marshal() the envelope.

jsmu simply abstracts the above logic into a single marshal or unmarshal call as necessary and alleviates you from having to maintain large type switches, constructor tables, or whatever other mechanism you perform the above logic with.

Register

jsmu requires that ConcreteType(s) be registered along with their TypeName and supports two conventions for supplying the TypeName.

You can embed a TypeName field directly into your struct:

type MyType struct {
	jsmu.TypeName `jsmu:"my-type"`
	//
	String string `json:"string"`
	Number int `json:"number"`
}
var mu jsmu.MU
mu.Register(&MyType{})

Or you can pass a TypeName value during the call to Register():

type MyType struct {
	String string `json:"string"`
	Number int `json:"number"`
}
//
var mu jsmu.MU
mu.Register(&MyType{}, jsmu.TypeName("my-type"))

Messages and Envelopes

Applications want to send messages. In order for an endpoint to unpack an arbitrary message into a concrete type we need to send type information along with the message (this was referred to as TypeName above).

In other words the most basic message format becomes:

{
	"type"     : int|string     // Uniquely describes the type for the "message" field.
	"message"  : any            // The message (broadcast|request|reply) the application wanted to send.
}

Conceptually we can think of this type wrapped around the "message" as the envelope.

jsmu allows you to use any custom type as an envelope by exposing and expecting the Enveloper interface:

type CustomEnvelope struct {
	// Must implement jsmu.Enveloper interface
}
my := &jsmu.MU{
	EnveloperFn : func() Enveloper{ return &CustomEnvelope{} },
}

If you leave the EnveloperFn field as nil then DefaultEnveloperFunc is used and your JSON needs to conform to the structure defined by Envelope.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrAlreadyRegistered is returned during Register() if the type string is already registered.
	ErrAlreadyRegistered = fmt.Errorf("already registered")
	// ErrMissingTypeName is returned during Register() if the type string can not be located.
	ErrMissingTypeName = fmt.Errorf("missing type name")
	// ErrNothingRegistered is returned during MU.Marshal() and MU.Unmarshal() when no types have been registered.
	ErrNothingRegistered = fmt.Errorf("nothing registered")
	// ErrUnregisteredType is returned during MU.Marshal() and MU.Unmarshal() when the type has not been registered.
	ErrUnregisteredType = fmt.Errorf("unregistered type")
)
View Source
var (
	// DefaultEnveloperFunc creates and returns an *Envelope from this package.
	DefaultEnveloperFunc = func() Enveloper {
		return &Envelope{}
	}
)
View Source
var (
	// DefaultMarshaller is the Marshaller used when no Marshaller is provided to MU.
	DefaultMarshaller = &JSONMarshaller{}
)

Functions

This section is empty.

Types

type Envelope

type Envelope struct {
	Type string          `json:"type"`
	Id   string          `json:"id"`
	Raw  json.RawMessage `json:"message"`
	// contains filtered or unexported fields
}

Envelope is a default Enveloper for basic needs.

JSON must conform to this format:

{
	"type"       : string,  // A string uniquely identifying "message".
	"id"         : string,  // An optional unique message ID; provided as a convenience for request-reply message flow.
	"message"    : {},      // Any JSON data your application can receive.
}

func (*Envelope) GetMessage

func (me *Envelope) GetMessage() interface{}

GetMessage returns the message in the envelope.

func (*Envelope) GetRawMessage

func (me *Envelope) GetRawMessage() json.RawMessage

GetRawMessage returns the raw JSON message in the envelope.

func (*Envelope) GetTypeName

func (me *Envelope) GetTypeName() string

GetTypeName returns the type name string.

func (*Envelope) SetMessage

func (me *Envelope) SetMessage(message interface{})

SetMessage sets the message in the envelope.

func (*Envelope) SetRawMessage

func (me *Envelope) SetRawMessage(raw json.RawMessage)

SetRawMessage sets the raw JSON message in the envelope.

func (*Envelope) SetTypeName

func (me *Envelope) SetTypeName(typeName string)

SetTypeName sets the type name string.

type Enveloper

type Enveloper interface {
	// GetMessage returns the message in the envelope.
	GetMessage() interface{}
	// SetMessage sets the message in the envelope.
	SetMessage(interface{})
	// GetRawMessage returns the raw JSON message in the envelope.
	GetRawMessage() json.RawMessage
	// SetRawMessage sets the raw JSON message in the envelope.
	SetRawMessage(json.RawMessage)
	// GetTypeName returns the type name string.
	GetTypeName() string
	// SetTypeName sets the type name string.
	SetTypeName(string)
}

Enveloper is the interface for message Envelopes.

type EnveloperFunc

type EnveloperFunc func() Enveloper

EnveloperFunc is a function that creates a new Enveloper.

type JSONMarshaller

type JSONMarshaller struct{}

JSONMarshaller implements Marshaller with JSON encoding.

func (*JSONMarshaller) Marshal

func (me *JSONMarshaller) Marshal(v interface{}) ([]byte, error)

Marshal marshals v into the expected encoding.

func (*JSONMarshaller) Unmarshal

func (me *JSONMarshaller) Unmarshal(data []byte, v interface{}) error

Unmarshal unmarshals data into v.

type MU

type MU struct {
	//
	// EnveloperFn is the function that creates a new envelope when one is needed.  If not provided
	// (aka left as nil) then DefaultEnveloperFunc is used and your JSON must conform to the format
	// described for type Envelope.
	EnveloperFn EnveloperFunc
	//
	// Marshaller is the implementation for marshalling and unmarshalling data.  If not provided
	// (aka left as nil) then a DefaultMarshaller is used; DefaultMarshaller uses json.Marshal() and
	// json.Unmarshal().
	Marshaller Marshaller
	//
	// StructTag specifies the struct tag name to use when inspecting types during register.  If not
	// set will default to "jsmu".
	StructTag string
	// contains filtered or unexported fields
}

MU marshals|unmarshals JavaScript encoded messages.

Example
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

func main() {
	// This example demonstrates:
	//	+ Register() when the type information is embedded with jsmu.TypeName.
	//	+ Unmarshal()

	type Person struct {
		jsmu.TypeName `js:"-" jsmu:"person"`
		//
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	type Animal struct {
		jsmu.TypeName `js:"-" jsmu:"animal"`
		//
		Name string `json:"name"`
		Says string `json:"says"`
	}
	//
	mu := &jsmu.MU{
		// EnveloperFn: nil,  // jsmu.DefaultEnveloperFunc is the default.
		// StructTag  : "",   // "jsmu" is the default.
	}
	mu.MustRegister(&Person{})
	mu.MustRegister(&Animal{})
	//
	strings := []string{
		`{
			"type" : "person",
			"message" : {
				"name" : "Bob",
				"age" : 40
			}
		}`,
		`{
			"type" : "animal",
			"message" : {
				"name" : "cat",
				"says" : "meow"
			}
		}`,
		`{
			"type" : "person",
			"message" : {
				"name" : "Sally",
				"age" : 30
			}
		}`,
		`{
			"type" : "animal",
			"message" : {
				"name" : "cow",
				"says" : "moo"
			}
		}`,
	}
	var envelope jsmu.Enveloper
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		switch message := envelope.GetMessage().(type) {
		case *Animal:
			fmt.Printf("A %v says, \"%v.\"\n", message.Name, message.Says)
		case *Person:
			fmt.Printf("%v is %v year(s) old.\n", message.Name, message.Age)
		}
	}

}
Output:

Bob is 40 year(s) old.
A cat says, "meow."
Sally is 30 year(s) old.
A cow says, "moo."
Example (ApiRequest)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

type ApiGetPerson struct {
	jsmu.TypeName `json:"-" jsmu:"get/person"`
	//
	Id     int     `json:"id"`
	Person *Person `json:"person"`
}

func main() {
	//
	people := map[int]*Person{
		10: {
			Name: "Bob",
			Age:  40,
		},
		20: {
			Name: "Sally",
			Age:  32,
		},
	}
	//
	mu := &jsmu.MU{}
	mu.MustRegister(&ApiGetPerson{})
	//
	strings := []string{
		`{
			"type" : "get/person",
			"id" : "first",
			"message" : {
				"id" : 20
			}
		}`,
		`{
			"type" : "get/person",
			"id" : "second",
			"message" : {
				"id" : 10
			}
		}`,
	}
	var envelope jsmu.Enveloper
	var response []byte
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		switch message := envelope.GetMessage().(type) {
		case *ApiGetPerson:
			if person, ok := people[message.Id]; ok {
				message.Person = person
			}
		}
		if response, err = mu.Marshal(envelope); err != nil {
			fmt.Println(err)
			return
		}
		fmt.Printf("%v\n", string(response))
	}

}
Output:

{"type":"get/person","id":"first","message":{"id":20,"person":{"name":"Sally","age":32}}}
{"type":"get/person","id":"second","message":{"id":10,"person":{"name":"Bob","age":40}}}
Example (Arrays)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

func main() {
	// This example shows how to register slices.

	type Person struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	type Animal struct {
		Name string `json:"name"`
		Says string `json:"says"`
	}
	//
	mu := &jsmu.MU{}
	mu.MustRegister([]*Person{}, jsmu.TypeName("people"))
	mu.MustRegister([]*Animal{}, jsmu.TypeName("animals"))
	//
	strings := []string{
		`{
			"type" : "people",
			"message" : [{
				"name" : "Bob",
				"age" : 40
			}, {
				"name" : "Sally",
				"age" : 30
			}]
		}`,
		`{
			"type" : "animals",
			"message" : [{
				"name" : "cat",
				"says" : "meow"
			}, {
				"name" : "cow",
				"says" : "moo"
			}]
		}`,
	}
	var envelope jsmu.Enveloper
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		switch message := envelope.GetMessage().(type) {
		case []*Animal:
			for _, animal := range message {
				fmt.Printf("A %v says, \"%v.\"\n", animal.Name, animal.Says)
			}
		case []*Person:
			for _, person := range message {
				fmt.Printf("%v is %v year(s) old.\n", person.Name, person.Age)
			}
		}
	}

	var buf []byte
	people := []*Person{
		{Name: "Larry", Age: 42},
		{Name: "Curly", Age: 48},
		{Name: "Moe", Age: 46},
	}
	if buf, err = mu.Marshal(people); err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%v\n", string(buf))

}
Output:

Bob is 40 year(s) old.
Sally is 30 year(s) old.
A cat says, "meow."
A cow says, "moo."
{"type":"people","id":"","message":[{"name":"Larry","age":42},{"name":"Curly","age":48},{"name":"Moe","age":46}]}
Example (CustomEnvelope)
package main

// This example demonstrates using a custom envelope with a JSON structure not expected by jsmu.Envelope.

import (
	"encoding/json"
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

// CustomEnvelope is for JSON that has a custom structure.
type CustomEnvelope struct {
	TypeInfo string          `json:"typeInfo"`
	Payload  json.RawMessage `json:"payload"`
	CustomA  string          `json:"customA"`
	CustomB  string          `json:"customB"`
	data     interface{}     `json:"-"`
}

// GetMessage returns the message in the envelope.
func (me *CustomEnvelope) GetMessage() interface{} {
	return me.data
}

// SetMessage sets the message in the envelope.
func (me *CustomEnvelope) SetMessage(message interface{}) {
	me.data = message
}

// GetRawMessage returns the raw JSON message in the envelope.
func (me *CustomEnvelope) GetRawMessage() json.RawMessage {
	return me.Payload
}

// SetRawMessage sets the raw JSON message in the envelope.
func (me *CustomEnvelope) SetRawMessage(raw json.RawMessage) {
	me.Payload = raw
}

// GetTypeName returns the type name string.
func (me *CustomEnvelope) GetTypeName() string {
	return me.TypeInfo
}

// SetTypeName sets the type name string.
func (me *CustomEnvelope) SetTypeName(typeInfo string) {
	me.TypeInfo = typeInfo
}

func main() {
	type Person struct {
		jsmu.TypeName `js:"-" jsmu:"person"`
		//
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	type Animal struct {
		jsmu.TypeName `js:"-" jsmu:"animal"`
		//
		Name string `json:"name"`
		Says string `json:"says"`
	}
	//
	mu := &jsmu.MU{
		EnveloperFn: func() jsmu.Enveloper {
			return &CustomEnvelope{}
		},
		// StructTag  : "",   // "jsmu" is the default.
	}
	mu.MustRegister(&Person{})
	mu.MustRegister(&Animal{})
	//
	strings := []string{
		`{
			"typeInfo" : "person",
			"payload" : {
				"name" : "Bob",
				"age" : 40
			},
			"customA" : "Hello!",
			"customB" : "Goodbye!"
		}`,
		`{
			"typeInfo" : "animal",
			"payload" : {
				"name" : "cat",
				"says" : "meow"
			},
			"customA" : "Foo",
			"customB" : "Bar"
		}`,
		`{
			"typeInfo" : "person",
			"payload" : {
				"name" : "Sally",
				"age" : 30
			},
			"customA" : "qwerty",
			"customB" : "dvorak"
		}`,
		`{
			"typeInfo" : "animal",
			"payload" : {
				"name" : "cow",
				"says" : "moo"
			},
			"customA" : "Batman",
			"customB" : "Robin"
		}`,
	}
	var envelope jsmu.Enveloper
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		custom := envelope.(*CustomEnvelope)
		switch message := envelope.GetMessage().(type) {
		case *Animal:
			fmt.Printf("A %v says, \"%v;\" [%v,%v].\n", message.Name, message.Says, custom.CustomA, custom.CustomB)
		case *Person:
			fmt.Printf("%v is %v year(s) old; [%v,%v].\n", message.Name, message.Age, custom.CustomA, custom.CustomB)
		}
	}

}
Output:

Bob is 40 year(s) old; [Hello!,Goodbye!].
A cat says, "meow;" [Foo,Bar].
Sally is 30 year(s) old; [qwerty,dvorak].
A cow says, "moo;" [Batman,Robin].
Example (MessageFactory)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

func main() {
	// This example shows how to provide a constructor or factory function for instantiating
	// your types if necessary.

	type Person struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	// We create a constructor function compatible with jsmu.MessageFunc.
	NewPerson := func() (interface{}, error) {
		fmt.Println("Created a person!")
		return &Person{}, nil
	}
	//
	mu := &jsmu.MU{
		// EnveloperFn: nil,  // jsmu.DefaultEnveloperFunc is the default.
		// StructTag  : "",   // "jsmu" is the default.
	}
	// Pass the NewPerson constructor during registration.
	mu.MustRegister(&Person{}, jsmu.MessageFunc(NewPerson), jsmu.TypeName("person"))
	//
	strings := []string{
		`{
			"type" : "person",
			"message" : {
				"name" : "Bob",
				"age" : 40
			}
		}`,
		`{
			"type" : "person",
			"message" : {
				"name" : "Sally",
				"age" : 30
			}
		}`,
	}
	var envelope jsmu.Enveloper
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		switch message := envelope.GetMessage().(type) {
		case *Person:
			fmt.Printf("%v is %v year(s) old.\n", message.Name, message.Age)
		}
	}

}
Output:

Created a person!
Bob is 40 year(s) old.
Created a person!
Sally is 30 year(s) old.
Example (WithoutEmbed)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/jsmu"
)

func main() {
	// This example does not embed jsmu.TypeName into the registered structs and
	// instead passes that information in the call to Register().
	//
	type Person struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	type Animal struct {
		Name string `json:"name"`
		Says string `json:"says"`
	}
	//
	mu := &jsmu.MU{}
	mu.MustRegister(&Person{}, jsmu.TypeName("person"))
	mu.MustRegister(&Animal{}, jsmu.TypeName("animal"))
	//
	strings := []string{
		`{
			"type" : "person",
			"message" : {
				"name" : "Bob",
				"age" : 40
			}
		}`,
		`{
			"type" : "animal",
			"message" : {
				"name" : "cat",
				"says" : "meow"
			}
		}`,
		`{
			"type" : "person",
			"message" : {
				"name" : "Sally",
				"age" : 30
			}
		}`,
		`{
			"type" : "animal",
			"message" : {
				"name" : "cow",
				"says" : "moo"
			}
		}`,
	}
	var envelope jsmu.Enveloper
	var err error
	for _, str := range strings {
		if envelope, err = mu.Unmarshal([]byte(str)); err != nil {
			fmt.Println(err)
			return
		}
		switch message := envelope.GetMessage().(type) {
		case *Animal:
			fmt.Printf("A %v says, \"%v.\"\n", message.Name, message.Says)
		case *Person:
			fmt.Printf("%v is %v year(s) old.\n", message.Name, message.Age)
		}
	}

}
Output:

Bob is 40 year(s) old.
A cat says, "meow."
Sally is 30 year(s) old.
A cow says, "moo."

func (*MU) Marshal

func (me *MU) Marshal(value interface{}) ([]byte, error)

Marshal marshals the incoming value. If value is already an Enveloper then MU.Marshaller.Marshal(value) is returned. Otherwise value is wrapped in a new envelope and MU.Marshaller.Marshal(NewEnvelope{value}) is returned.

func (*MU) MustRegister

func (me *MU) MustRegister(value interface{}, opts ...interface{})

MustRegister is similar to Register() except it panic if an error is returned.

func (*MU) Register

func (me *MU) Register(value interface{}, opts ...interface{}) error

Register registers a type instance with the MU.

Calls to Register are not goroutine safe; it is the caller's responsibility to coordinate locking if registering values from goroutines.

func (*MU) Unmarshal

func (me *MU) Unmarshal(data []byte) (Enveloper, error)

Unmarshal unmarshals a JSON string into a registered type and the envelope that contained it. An error is returned if the JSON can not be unmarshalled or the type is unregistered.

type Marshaller

type Marshaller interface {
	// Marshal marshals v into the expected encoding.
	Marshal(v interface{}) ([]byte, error)
	// Unmarshal unmarshals data into v.
	Unmarshal(data []byte, v interface{}) error
}

Marshaller is the interface for marshalling data.

type MessageFunc

type MessageFunc func() (interface{}, error)

MessageFunc is a function that instantiates a type.

type MockMarshaller

type MockMarshaller struct {
	MarshalImplementation   func(v interface{}) ([]byte, error)
	UnmarshalImplementation func(data []byte, v interface{}) error
}

MockMarshaller implements Marshaller but allows you to swap out the implementation with functions.

Consider using this during unit testing.

func (*MockMarshaller) Marshal

func (me *MockMarshaller) Marshal(v interface{}) ([]byte, error)

Marshal marshals v into the expected encoding.

func (*MockMarshaller) Unmarshal

func (me *MockMarshaller) Unmarshal(data []byte, v interface{}) error

Unmarshal unmarshals data into v.

type TypeName

type TypeName string

TypeName represents a jsmu type name. Embed the TypeName type into a struct and set the appropriate struct tag to configure the table name.

Directories

Path Synopsis
Package data provides JSON data for benchmarks and tests for jsmu.
Package data provides JSON data for benchmarks and tests for jsmu.

Jump to

Keyboard shortcuts

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