modtracker

package module
v0.0.0-...-d286f52 Latest Latest
Warning

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

Go to latest
Published: Feb 1, 2017 License: Apache-2.0 Imports: 8 Imported by: 0

README

modtracker

JSON unmarshaling in Go that includes detection of the fields that were modified during unmarshaling

If you are doing a CRUD update via a REST API using JSON, you probably only want to update the database fields that were actually sent by the client. The standard Go JSON Unmarshaler doesn't provide this information.

The modtracker package provides a way to discover this information. You can use it in a few ways. First, you can call modtracker.UnmarshalJSON directly:

type Sample struct {
	FirstName *string
	LastName  *string
	Age       *int
}

func main() {
   var s Sample
   data := `
       {
   		"FirstName": "Homer",
   		"LastName": "Simpson",
   		"Age": 37
   	}
   `
   fmt.Println("converting", data)
   modified, err := modtracker.Unmarshal([]byte(data), &s)
   if err != nil {
   	fmt.Printf("%+v\n", err)
   } else {
   	fmt.Println(s,modified)
   }
}

You can wrap the call to modtracker.Unmarshal inside of an UnmarshalJSON method:

 type Sample struct {
 	FirstName *string
 	LastName  *string
 	Age       *int
 	modified  []string
 }

func (s *Sample) UnmarshalJSON(data []byte) error {
	var err error
	s.modified, err = modtracker.Unmarshal(data, s)
	return err
}

func (s *Sample) GetModified() []string {
	return s.modified
}

func main() {
	var s Sample
	data := `
	    {
			"FirstName": "Homer",
    		"LastName": "Simpson",
    		"Age": 37
    	}
    `
	fmt.Println("converting", data)
	err := json.Unmarshal([]byte(data), &s)
	if err != nil {
		fmt.Printf("%+v\n", err)
	} else {
		fmt.Println(s)
	}
}

You can avoid some of the cost of reflection by pre-caclulating the fields, tags, and types using the BuildJSONUnmarshaler function:

var sampleUnmarshaler modtracker.Unmarshaler

func init() {
	var err error
	sampleUnmarshaler, err = modtracker.BuildJSONUnmarshaler((*Sample)(nil))
	if err != nil {
		panic(err)
	}
}

type Sample struct {
 	FirstName *string
 	LastName  *string
 	Age       *int
 	modified  []string
 }

func (s *Sample) UnmarshalJSON(data []byte) error {
	var err error
	s.modified, err = sampleUnmarshaler(data, s)
	return err
}

func (s *Sample) GetModified() []string {
	return s.modified
}

func main() {
	var s Sample
	data := `
	    {
			"FirstName": "Homer",
    		"LastName": "Simpson",
    		"Age": 37
    	}
    `
	fmt.Println("converting", data)
	err := json.Unmarshal([]byte(data), &s)
	if err != nil {
		fmt.Printf("%+v\n", err)
	} else {
		fmt.Println(s)
	}
}

The modtracker unmarshalers respect json struct tags and work with both pointer and value fields. Fields of function type and channel type are ignored.

Contributors:

We welcome your interest in Capital One’s Open Source Projects (the “Project”). Any Contributor to the project must accept and sign a CLA indicating agreement to the license terms. Except for the license granted in this CLA to Capital One and to recipients of software distributed by Capital One, you reserve all right, title, and interest in and to your contributions; this CLA does not impact your rights to use your own contributions for any other purpose.

Link to CLA

This project adheres to the Open Source Code of Conduct. By participating, you are expected to honor this code.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildJSONUnmarshaler

func BuildJSONUnmarshaler(s interface{}) (func([]byte, interface{}) ([]string, error), error)

BuildJSONUnmarshaler generates a custom implementation of the Unmarshaler type for the type of the provided struct. The preferred way to use BuildJSONUnmarshaler is to create a package-level variable and assign it in init with a nil instance of the type:

type Sample struct {
	FirstName *string
	LastName  *string
	Age       *int
	Inner     *struct {
		Address string
	}
	Pet      string
	Company  string `json:"company"`
	modified []string
}

var sampleUnmarshaler modtracker.Unmarshaler

func init() {
	var err error
	sampleUnmarshaler, err = modtracker.BuildJSONUnmarshaler((*Sample)(nil))
	if err !=  nil {
		panic(err)
	}
}

func (s *Sample) UnmarshalJSON(data []byte) error {
	modified, err := sampleUnmarshaler(data, s)
	if err != nil {
		return err
	}
	s.modified = modified
	return nil
}

func UnmarshalJSON

func UnmarshalJSON(data []byte, s interface{}) ([]string, error)

UnmarshalJSON provides the default implementation of the Unmarshaler type. It will rediscover the fields in the structure each time it is called; to improve performance, use BuildJSONUnmarshaler to create an Unmarshaler instance with the struct fields pre-calculated.

Types

type Modifiable

type Modifiable interface {
	GetModified() []string
}

Modifiable is implemented by struct types that contain a list of their fields that were populated from JSON. If a value for a field, even null, was provided in the JSON, the name of the field appears in the slice of strings.

type Unmarshaler

type Unmarshaler func([]byte, interface{}) ([]string, error)

An Unmarshaler takes in JSON in the first parameter, a pointer to a struct in the second parameter, populates the struct with the JSON and returns the modified fields as a slice of strings. In case of error, the struct might be partially populated. If there is an error, the modified field slice will be nil.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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