gtly

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2020 License: Apache-2.0 Imports: 6 Imported by: 6

README

gtly - Dynamic data structure with go lang.

GoReportCard GoDoc

This library is compatible with Go 1.15+

Please refer to CHANGELOG.md if you encounter breaking changes.

Motivation

The goal of this project is to use dynamic data types without defining native GO structs with minimum memory footprint. Alternative would be just using map, but that is way too inefficient. Having dynamic type safe objects enables building generic solution for REST/Micro Service/ETL etc. To build dynamic solution dynamic object should be easily transferable into common format like JSON, AVRO, ProtoBuf, etc....

Introduction

Gtly complex data type use slice based storage with Proto reference to reduce memory footprint and to avoid reflection. An proto instance is shared across all Object and Collection of the same type. Proto control mapping between field and field position withing object, or slice item. What's more proto field define field meta data like DateLayout, OutputName controlled by proto CaseFormat dynamically.

Usage

Object
package mypacakge

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func NewObject_Usage() {
	fooProvider := gtly.NewProvider("foo",  //create foo type 
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt("2006-01-02T15:04:05Z07:00")),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)
    //create an instance of foo type
	foo1 := fooProvider.NewObject()
	foo1.SetInt("id", 1)
	foo1.SetString("firsName", "Adam")
	foo1.SetTime("updated", time.Now())
	foo1.SetValue("numbers", []int{1, 2, 3})
	JSON, err := json.Marshal(foo1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
    //Prints: {"id":1,"firsName":"Adam","updated":"2020-09-25T20:43:40-07:00","numbers":[1,2,3]}
    //change foo type output to upper underscore
	fooProvider.OutputCaseFormat(gtly.CaseLowerCamel, gtly.CaseUpperUnderscore)
	JSON, _ = json.Marshal(foo1)
	fmt.Printf("%s\n", JSON)
    //Prints: {"ID":1,"FIRS_NAME":"Adam","UPDATED":"2020-09-25T20:43:40-07:00","NUMBERS":[1,2,3]}
    //change foo type output to lower underscore
	fooProvider.OutputCaseFormat(gtly.CaseLowerCamel, gtly.CaseLowerUnderscore)
    foo1.SetBool("active", true) //add dynamically new field
	foo1.SetString("description", "some description") // set value for existing field
	JSON, _ = json.Marshal(foo1)
	fmt.Printf("%s\n", JSON)
    //Prints: {"id":1,"firs_name":"Adam","description":"some description","updated":"2020-09-25T20:43:40-07:00","numbers":[1,2,3],"active":true}
   //create another instance of foo type
    foo2 := fooProvider.NewObject()
    JSON, _ = json.Marshal(foo2)
	fmt.Printf("%s\n", JSON)
}
Array
package mypacakge

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func NewArray_Usage() {
    fooProvider := gtly.NewProvider("foo",
        gtly.NewField("id", gtly.FieldTypeInt),
        gtly.NewField("firsName", gtly.FieldTypeString),
        gtly.NewField("income", gtly.FieldTypeFloat),
        gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
        gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
        gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
    )
    fooArray1 := fooProvider.NewArray()
    for i:=0;i<10;i++ {
        foo1 := fooProvider.NewObject()
        foo1.SetInt("id", 1)
        foo1.SetFloat("income", 64000.0*float64(1+(10/(i+1))))
        foo1.SetString("firsName", "Adam")
        fooArray1.AddObject(foo1)
    }
    now := time.Now()
    fooArray1.Add(map[string]interface{}{
        "id":      100,
        "firsName":    "Tom",
        "updated": now,
    })
    totalIncome := 0.0
    incomeField := fooProvider.Field("income")
    //Iterating collection
    err := fooArray1.Objects(func(object *gtly.Object) (bool, error) {
        fmt.Printf("id: %v\n",  object.Int("id"))
        fmt.Printf("name: %v\n",  object.String("name"))
        totalIncome +=  object.FloatAt(incomeField.Index)
        return true, nil
    })
    fmt.Printf("income total: %v\n", totalIncome)
    if err != nil {
        log.Fatal(err)
    }
    JSON, err := json.Marshal(fooArray1)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s", JSON)
}

Map
package mypacakge

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func NewMap_Usage() {
	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)
	//Creates a map keyed by id field
	aMap := fooProvider.NewMap(gtly.NewIndex([]string{"id"}))
	for i := 0; i < 10; i++ {
		foo := fooProvider.NewObject()
		foo.SetInt("id", i)
		foo.SetString("firsName", fmt.Sprintf("Name %v", i))
		aMap.AddObject(foo)
	}
	//Accessing map
	foo1 := aMap.Object("1")
	JSON, err := json.Marshal(foo1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
    //Prints  {"id":1,"firsName":"Name 1","updated":null,"numbers":null}
	//Iterating map
    aMap.Pairs(func(key string, item *gtly.Object) (bool, error) {
        fmt.Printf("id: %v\n",  item.Int("id"))
        fmt.Printf("name: %v\n",  item.String("name"))
        return true, nil
    })
	JSON, err = json.Marshal(aMap)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//[{"id":1,"firsName":"Name 1","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","updated":null,"numbers":null},{"id":4,"firsName":"Name 4","updated":null,"numbers":null},{"id":6,"firsName":"Name 6","updated":null,"numbers":null},{"id":8,"firsName":"Name 8","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","updated":null,"numbers":null},{"id":0,"firsName":"Name 0","updated":null,"numbers":null},{"id":2,"firsName":"Name 2","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","updated":null,"numbers":null}]
}
MultiMap
func NewMultiMap_Usage() {
	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("city", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)
	//Creates a multi map keyed by id field
	aMap := fooProvider.NewMultimap(gtly.NewIndex([]string{"city"}))
	for i := 0; i < 10; i++ {
		foo := fooProvider.NewObject()
		foo.SetInt("id", i)
		foo.SetString("firsName", fmt.Sprintf("Name %v", i))
		if i % 2 ==0 {
			foo.SetString("city", "Cracow")
		} else {
			foo.SetString("city", "Warsaw")
		}
		aMap.AddObject(foo)
	}
	//Accessing map
	fooInWarsawSlice := aMap.Slice("Warsaw")
	JSON, err := json.Marshal(fooInWarsawSlice)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//Prints [{"id":1,"firsName":"Name 1","city":"Warsaw","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","city":"Warsaw","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","city":"Warsaw","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","city":"Warsaw","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","city":"Warsaw","updated":null,"numbers":null}]
	//Iterating multi map
	err = aMap.Slices(func(key string, value *gtly.Array) (bool, error) {
		fmt.Printf("%v -> %v\n", key, value.Size())
		return true, nil
	})
	if err != nil {
		log.Fatal(err)
	}
	JSON, err = json.Marshal(aMap)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//[{"id":0,"firsName":"Name 0","city":"Cracow","updated":null,"numbers":null},{"id":2,"firsName":"Name 2","city":"Cracow","updated":null,"numbers":null},{"id":4,"firsName":"Name 4","city":"Cracow","updated":null,"numbers":null},{"id":6,"firsName":"Name 6","city":"Cracow","updated":null,"numbers":null},{"id":8,"firsName":"Name 8","city":"Cracow","updated":null,"numbers":null},{"id":1,"firsName":"Name 1","city":"Warsaw","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","city":"Warsaw","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","city":"Warsaw","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","city":"Warsaw","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","city":"Warsaw","updated":null,"numbers":null}]

}

Contributing to gtly

Gtly is an open source project and contributors are welcome!

See TODO list

License

The source code is made available under the terms of the Apache License, Version 2, as stated in the file LICENSE.

Individual files may be made available under their own specific license, all compatible with Apache License, Version 2. Please see individual files for details.

Credits and Acknowledgements

Library Author: Adrian Witas

Documentation

Overview

Package gtly defines generic data types

To reduce memory footprint and to avoid reflection, slice position based storage is used with shared _proto object. Proto object controls conversion between field and field position withing given object, slice item

Index

Examples

Constants

View Source
const (
	//CaseUpper  upper case
	CaseUpper = "Upper"
	//CaseLower lower case
	CaseLower = "Lower"
	//CaseUpperCamel upper camel
	CaseUpperCamel = "UpperCamel"
	//CaseLowerCamel lower camel
	CaseLowerCamel = "LowerCamel"
	//CaseUpperUnderscore upper underscore
	CaseUpperUnderscore = "UpperUnderscore"
	//CaseLowerUnderscore lower underscore
	CaseLowerUnderscore = "LowerUnderscore"
)
View Source
const (
	//FieldTypeInt int type
	FieldTypeInt = "int"
	//FieldTypeFloat float type
	FieldTypeFloat = "float"
	//FieldTypeBool bool type
	FieldTypeBool = "bool"
	//FieldTypeString string type
	FieldTypeString = "string"
	//FieldTypeTime time type
	FieldTypeTime = "time"
	//FieldTypeBytes bytes type
	FieldTypeBytes = "bytes"
	//FieldTypeArray array type
	FieldTypeArray = "array"
	//FieldTypeObject object type
	FieldTypeObject = "object"
)

Variables

View Source
var CaseFormat = map[string]int{
	CaseUpper:           toolbox.CaseUpper,
	CaseLower:           toolbox.CaseLower,
	CaseUpperCamel:      toolbox.CaseUpperCamel,
	CaseLowerCamel:      toolbox.CaseLowerCamel,
	CaseUpperUnderscore: toolbox.CaseUpperUnderscore,
	CaseLowerUnderscore: toolbox.CaseLowerUnderscore,
}

CaseFormat defines case format map

View Source
var NilValue = make([]*interface{}, 1)[0]

NilValue is used to discriminate between unset fileds, and set filed with nil value (for REST patch operation)

Functions

func ValidateCaseFormat

func ValidateCaseFormat(caseFormat string) error

ValidateCaseFormat checks if case format is valid

func Value

func Value(value interface{}) interface{}

Value returns value

Types

type Array

type Array struct {
	// contains filtered or unexported fields
}

Array represents dynamic object slice

func (*Array) Add

func (s *Array) Add(aMap map[string]interface{})

Add add elements to a slice

func (*Array) AddObject

func (s *Array) AddObject(object *Object)

AddObject adds object

func (Array) Compact

func (s Array) Compact() *Compacted

Compact converts array into compacted collection

func (Array) First

func (s Array) First() *Object

First returns first elements on the slice

func (*Array) Objects

func (s *Array) Objects(handler func(item *Object) (bool, error)) error

Objects iterate over object slice, any update to objects are applied to the slice

func (*Array) Proto

func (s *Array) Proto() *Proto

Proto returns slice _proto

func (Array) Range

func (s Array) Range(handler func(item interface{}) (bool, error)) error

Range call handler with every slice element

func (Array) Size

func (s Array) Size() int

Size return slice size

type Collection

type Collection interface {
	//Add adds item to collection
	Add(values map[string]interface{})
	//AddObject add an object
	AddObject(object *Object)
	//Range calls handler with collection item
	Range(handler func(item interface{}) (toContinue bool, err error)) error
	//Objects calls handler with collection item object
	Objects(handler func(item *Object) (toContinue bool, err error)) error
	//Size returns collection size
	Size() int
	//Proto return collection component prototype
	Proto() *Proto
	//First returns first object
	First() *Object
	//Compact returns compacted collection representation
	Compact() *Compacted
}

Collection represents generic collection

type Compacted

type Compacted struct {
	Fields []*Field
	Data   [][]interface{}
}

Compacted represents compacted collection

func (*Compacted) TransformBinary

func (c *Compacted) TransformBinary()

TransformBinary transform binary data into string

func (Compacted) Update

func (c Compacted) Update(collection Collection) error

Update updates collection

type Field

type Field struct {
	Name          string `json:",omitempty"`
	Index         int
	OmitEmpty     *bool  `json:",omitempty"`
	DateFormat    string `json:",omitempty"`
	DataLayout    string `json:",omitempty"`
	DataType      string `json:",omitempty"`
	InputName     string `json:",omitempty"`
	ComponentType string `json:",omitempty"`
	// contains filtered or unexported fields
}

Field represents dynamic filed

func NewField

func NewField(name, dataType string, options ...Option) *Field

NewField creates new fields

func (*Field) Get

func (f *Field) Get(values []interface{}) interface{}

Get returns field value

func (*Field) InitType

func (f *Field) InitType(value interface{})

InitType initialise filed type

func (*Field) IsEmpty

func (f *Field) IsEmpty(proto *Proto, value interface{}) bool

IsEmpty returns true if field value is empty

func (*Field) OutputName

func (f *Field) OutputName() string

OutputName returns field output Name

func (*Field) Set

func (f *Field) Set(value interface{}, result *[]interface{})

Set sets a field value

func (*Field) SetProvider

func (f *Field) SetProvider(provider *Provider)

SetProvider set provider

func (*Field) SetValue

func (f *Field) SetValue(value interface{}, result *[]interface{})

SetValue sets field value

func (*Field) ShallOmitEmpty

func (f *Field) ShallOmitEmpty(proto *Proto) bool

ShallOmitEmpty return true if shall omit empty

func (*Field) TimeLayout

func (f *Field) TimeLayout(proto *Proto) string

TimeLayout returns timelayout

type Index

type Index func(values interface{}) string

Index represents Index function

func NewIndex

func NewIndex(keys []string) Index

NewIndex returns an Index for supplied keys

type Map

type Map struct {
	// contains filtered or unexported fields
}

Map represents generic map

func (*Map) Add

func (m *Map) Add(values map[string]interface{})

Add add item to a map

func (*Map) AddObject

func (m *Map) AddObject(object *Object)

AddObject add object to the map

func (Map) Compact

func (m Map) Compact() *Compacted

Compact converts map into compacted object

func (Map) First

func (m Map) First() *Object

First return a first map elements

func (*Map) Object

func (m *Map) Object(key string) *Object

Object returns an object for specified key or nil

func (*Map) Objects

func (m *Map) Objects(handler func(item *Object) (bool, error)) error

Objects iterate over object slice, any update to objects are applied to the slice

func (*Map) Pairs

func (m *Map) Pairs(handler func(key string, item *Object) (bool, error)) error

Pairs iterate over object slice, any update to objects are applied to the slice

func (*Map) Proto

func (m *Map) Proto() *Proto

Proto returns map _proto

func (Map) Range

func (m Map) Range(handler func(item interface{}) (bool, error)) error

Range calls handler with every slice element

func (Map) Size

func (m Map) Size() int

Size return slice size

type Multimap

type Multimap struct {
	// contains filtered or unexported fields
}

Multimap represents generic multi map

func (*Multimap) Add

func (m *Multimap) Add(values map[string]interface{})

Add add item to a map

func (*Multimap) AddObject

func (m *Multimap) AddObject(object *Object)

AddObject add object into mulaitmap

func (Multimap) Compact

func (m Multimap) Compact() *Compacted

Compact returns compacted slice

func (Multimap) First

func (m Multimap) First() *Object

First returns an element from multimap

func (Multimap) IsNil

func (m Multimap) IsNil() bool

IsNil returns true if it's nil

func (*Multimap) Objects

func (m *Multimap) Objects(handler func(item *Object) (bool, error)) error

Objects call handler for every object in this collection

func (*Multimap) Proto

func (m *Multimap) Proto() *Proto

Proto returns multimap _proto

func (Multimap) Range

func (m Multimap) Range(handler func(item interface{}) (bool, error)) error

Range calls handler with every slice element

func (Multimap) Size

func (m Multimap) Size() int

Size return slice size

func (*Multimap) Slice

func (m *Multimap) Slice(key string) *Array

Slice returns a slice for specified key or nil

func (*Multimap) Slices

func (m *Multimap) Slices(handler func(key string, value *Array) (bool, error)) error

Slices iterate over object slice, any update to objects are applied to the slice

type Nilable

type Nilable interface {
	IsNil() bool
}

Nilable represent a type that can be nil

type Object

type Object struct {
	// contains filtered or unexported fields
}

Object represents dynamic object

func (*Object) AsMap

func (o *Object) AsMap() map[string]interface{}

AsMap return map

func (*Object) Bool

func (o *Object) Bool(name string) bool

Bool return bool for supplied field name

func (*Object) BoolAt

func (o *Object) BoolAt(index int) bool

BoolAt returns bool value for specified index

func (*Object) Float

func (o *Object) Float(name string) float64

Float returns float for supplied field name

func (*Object) FloatAt

func (o *Object) FloatAt(index int) float64

FloatAt returns float value for specified index

func (*Object) FloatValue

func (o *Object) FloatValue(name string) (*float64, error)

FloatValue return float for supplied Name

func (*Object) HasAt

func (o *Object) HasAt(index int) bool

HasAt returns true if has value

func (*Object) Init

func (o *Object) Init(values map[string]interface{})

Init initialise entire object

func (*Object) Int

func (o *Object) Int(name string) int

Int returns int for supplied field name

func (*Object) IntAt

func (o *Object) IntAt(index int) int

IntAt returns int value for specified index

func (*Object) IntValue

func (o *Object) IntValue(name string) (*int, error)

IntValue returns int value

func (*Object) IsNil

func (o *Object) IsNil() bool

IsNil returns true if object is nil

func (*Object) Proto

func (o *Object) Proto() *Proto

Proto returns object _proto

func (*Object) SetBool

func (o *Object) SetBool(name string, value bool)

SetBool sets string value

func (*Object) SetFloat

func (o *Object) SetFloat(name string, value float64)

SetFloat sets float values

func (*Object) SetInt

func (o *Object) SetInt(name string, value int)

SetInt sets int values

func (*Object) SetString

func (o *Object) SetString(name string, value string)

SetString sets string value

func (*Object) SetTime

func (o *Object) SetTime(name string, value time.Time)

SetTime sets string value

func (*Object) SetValue

func (o *Object) SetValue(name string, value interface{})

SetValue sets values

func (*Object) String

func (o *Object) String(name string) string

String return string for supplied field name

func (*Object) StringAt

func (o *Object) StringAt(index int) string

StringAt returns int value for specified index

func (*Object) StringValue

func (o *Object) StringValue(name string) *string

StringValue returns int value

func (*Object) Value

func (o *Object) Value(name string) interface{}

Value get value for supplied Name

func (*Object) ValueAt

func (o *Object) ValueAt(index int) interface{}

ValueAt get value for supplied filed Index

type Option

type Option func(field *Field)

Option represents field option

func ComponentTypeOpt

func ComponentTypeOpt(componentType string) Option

ComponentTypeOpt return a field component type option

func DateLayoutOpt

func DateLayoutOpt(layout string) Option

DateLayoutOpt field with data layout option

func OmitEmptyOpt

func OmitEmptyOpt(omitEmpty bool) Option

OmitEmptyOpt returns a field omit empty option

func ProviderOpt

func ProviderOpt(provider *Provider) Option

ProviderOpt return a field provider option

type Proto

type Proto struct {
	Name string

	OmitEmpty bool
	// contains filtered or unexported fields
}

Proto represents generic type prototype

func (*Proto) AddField

func (p *Proto) AddField(field *Field) *Field

AddField add fields

func (*Proto) Field

func (p *Proto) Field(name string) *Field

Field returns field for specified Name

func (*Proto) FieldWithValue

func (p *Proto) FieldWithValue(fieldName string, value interface{}) *Field

FieldWithValue returns existing filed , or create a new field

func (*Proto) Fields

func (p *Proto) Fields() []*Field

Fields returns fields list

func (*Proto) Hide

func (p *Proto) Hide(name string)

Hide set hidden flag for the field

func (*Proto) InputCaseFormat

func (p *Proto) InputCaseFormat(source, input string) error

InputCaseFormat set output case format

func (*Proto) Object

func (p *Proto) Object(values []interface{}) (*Object, error)

Object creates an object

func (*Proto) OutputCaseFormat

func (p *Proto) OutputCaseFormat(source, output string) error

OutputCaseFormat set output case format

func (*Proto) SetEmptyValues

func (p *Proto) SetEmptyValues(values ...interface{})

SetEmptyValues sets empty values, use only if empty values are non in default map: nil, empty string

func (*Proto) SetOmitEmpty

func (p *Proto) SetOmitEmpty(omitEmpty bool)

SetOmitEmpty sets omit empty flag

func (*Proto) Show

func (p *Proto) Show(name string)

Show remove hidden flag for supplied field

func (*Proto) SimpleName

func (p *Proto) SimpleName() string

SimpleName returns simple name

func (*Proto) Size

func (p *Proto) Size() int

Size returns _proto size

type Provider

type Provider struct {
	*Proto
}

Provider provides shares _proto data across all dynamic types

func NewProvider

func NewProvider(name string, fields ...*Field) *Provider

NewProvider creates provider

func (*Provider) NewArray

func (p *Provider) NewArray(items ...interface{}) *Array

NewArray creates a slice

Example

TestProvider_NewArray new array example

package main

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func main() {
	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("income", gtly.FieldTypeFloat),
		gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)
	fooArray1 := fooProvider.NewArray()

	for i := 0; i < 10; i++ {
		foo1 := fooProvider.NewObject()
		foo1.SetInt("id", 1)
		foo1.SetFloat("income", 64000.0*float64(1+(10/(i+1))))
		foo1.SetString("firsName", "Adam")
		fooArray1.AddObject(foo1)
	}

	now := time.Now()
	fooArray1.Add(map[string]interface{}{
		"id":       100,
		"firsName": "Tom",
		"updated":  now,
	})

	totalIncome := 0.0
	incomeField := fooProvider.Field("income")
	//Iterating collection
	err := fooArray1.Objects(func(object *gtly.Object) (bool, error) {
		fmt.Printf("id: %v\n", object.Int("id"))
		fmt.Printf("name: %v\n", object.String("name"))
		totalIncome += object.FloatAt(incomeField.Index)
		return true, nil
	})
	fmt.Printf("income total: %v\n", totalIncome)
	if err != nil {
		log.Fatal(err)
	}
	JSON, err := json.Marshal(fooArray1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s", JSON)
}

func (*Provider) NewMap

func (p *Provider) NewMap(index Index) *Map

NewMap creates a map of string and object

Example

ExampleProvider_NewMap new map example

package main

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func main() {

	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)

	//Creates a map keyed by id field
	aMap := fooProvider.NewMap(gtly.NewIndex([]string{"id"}))
	for i := 0; i < 10; i++ {
		foo := fooProvider.NewObject()
		foo.SetInt("id", i)
		foo.SetString("firsName", fmt.Sprintf("Name %v", i))
		aMap.AddObject(foo)
	}

	//Accessing map
	foo1 := aMap.Object("1")
	JSON, err := json.Marshal(foo1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)

	//Iterating map
	err = aMap.Pairs(func(key string, item *gtly.Object) (bool, error) {
		fmt.Printf("id: %v\n", item.Int("id"))
		fmt.Printf("name: %v\n", item.String("name"))
		return true, nil
	})
	if err != nil {
		log.Fatal(err)
	}

	JSON, err = json.Marshal(aMap)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//[{"id":1,"firsName":"Name 1","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","updated":null,"numbers":null},{"id":4,"firsName":"Name 4","updated":null,"numbers":null},{"id":6,"firsName":"Name 6","updated":null,"numbers":null},{"id":8,"firsName":"Name 8","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","updated":null,"numbers":null},{"id":0,"firsName":"Name 0","updated":null,"numbers":null},{"id":2,"firsName":"Name 2","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","updated":null,"numbers":null}]

}

func (*Provider) NewMultimap

func (p *Provider) NewMultimap(index Index) *Multimap

NewMultimap creates a multimap of string and slice

Example

ExampleProvider_NewMulti new multi example

package main

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func main() {
	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("city", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt(time.RFC3339)),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)

	//Creates a multi map keyed by id field
	aMap := fooProvider.NewMultimap(gtly.NewIndex([]string{"city"}))
	for i := 0; i < 10; i++ {
		foo := fooProvider.NewObject()
		foo.SetInt("id", i)
		foo.SetString("firsName", fmt.Sprintf("Name %v", i))
		if i%2 == 0 {
			foo.SetString("city", "Cracow")
		} else {
			foo.SetString("city", "Warsaw")
		}
		aMap.AddObject(foo)
	}

	//Accessing map
	fooInWarsawSlice := aMap.Slice("Warsaw")
	JSON, err := json.Marshal(fooInWarsawSlice)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//Prints [{"id":1,"firsName":"Name 1","city":"Warsaw","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","city":"Warsaw","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","city":"Warsaw","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","city":"Warsaw","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","city":"Warsaw","updated":null,"numbers":null}]

	//Iterating multi map
	err = aMap.Slices(func(key string, value *gtly.Array) (bool, error) {
		fmt.Printf("%v -> %v\n", key, value.Size())
		return true, nil
	})
	if err != nil {
		log.Fatal(err)
	}

	JSON, err = json.Marshal(aMap)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	//[{"id":0,"firsName":"Name 0","city":"Cracow","updated":null,"numbers":null},{"id":2,"firsName":"Name 2","city":"Cracow","updated":null,"numbers":null},{"id":4,"firsName":"Name 4","city":"Cracow","updated":null,"numbers":null},{"id":6,"firsName":"Name 6","city":"Cracow","updated":null,"numbers":null},{"id":8,"firsName":"Name 8","city":"Cracow","updated":null,"numbers":null},{"id":1,"firsName":"Name 1","city":"Warsaw","updated":null,"numbers":null},{"id":3,"firsName":"Name 3","city":"Warsaw","updated":null,"numbers":null},{"id":5,"firsName":"Name 5","city":"Warsaw","updated":null,"numbers":null},{"id":7,"firsName":"Name 7","city":"Warsaw","updated":null,"numbers":null},{"id":9,"firsName":"Name 9","city":"Warsaw","updated":null,"numbers":null}]

}

func (*Provider) NewObject

func (p *Provider) NewObject() *Object

NewObject creates an object

Example

ExampleProvider_NewObject new object example

package main

import (
	"fmt"
	"github.com/viant/gtly"
	"github.com/viant/gtly/codec/json"
	"log"
	"time"
)

func main() {

	fooProvider := gtly.NewProvider("foo",
		gtly.NewField("id", gtly.FieldTypeInt),
		gtly.NewField("firsName", gtly.FieldTypeString),
		gtly.NewField("description", gtly.FieldTypeString, gtly.OmitEmptyOpt(true)),
		gtly.NewField("updated", gtly.FieldTypeTime, gtly.DateLayoutOpt("2006-01-02T15:04:05Z07:00")),
		gtly.NewField("numbers", gtly.FieldTypeArray, gtly.ComponentTypeOpt(gtly.FieldTypeInt)),
	)
	foo1 := fooProvider.NewObject()
	foo1.SetInt("id", 1)
	foo1.SetString("firsName", "Adam")
	foo1.SetTime("updated", time.Now())
	foo1.SetValue("numbers", []int{1, 2, 3})

	JSON, err := json.Marshal(foo1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", JSON)
	fooProvider.OutputCaseFormat(gtly.CaseLowerCamel, gtly.CaseUpperUnderscore)
	JSON, _ = json.Marshal(foo1)
	fmt.Printf("%s\n", JSON)

	fooProvider.OutputCaseFormat(gtly.CaseLowerCamel, gtly.CaseLowerUnderscore)
	foo1.SetBool("active", true)
	foo1.SetString("description", "some description")

	JSON, _ = json.Marshal(foo1)
	fmt.Printf("%s\n", JSON)
}

func (*Provider) Object

func (p *Provider) Object(value interface{}) (*Object, error)

Object creates an object from struct or map

type Zeroable

type Zeroable interface {
	IsZero() bool
}

Zeroable represent uninitialise type

Directories

Path Synopsis
codec

Jump to

Keyboard shortcuts

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