go_data_chain

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 25, 2023 License: Apache-2.0 Imports: 4 Imported by: 1

README

go-data-chain Easy Navigation of complex interface{} data types

Description

Package to help navigate complex interface{} data types with auto casting of various types where possible.


When to use go-data-chain

  • Is you need to read data from complex interface{} for example when Unmarshal data into an interface.
  • Read data returned from an REST API call and you don't Unmarshal the data into a type but an interface.

Requirements


Project folders

Below is a description go-data-chain project folders and what they contain

Folder Description
examples yaml payload used to test the package
/ Main code

Installation and Basic usage

This will take you through the steps to install and get go-data-chain up and running.

1. Install

Once you have installed golang you can run the following command to get go-data-chain

go get github.com/Mrpye/go-data-chain
2. Include in your project
    include github.com/Mrpye/go-data-chain

Handling missing keys and index

The way go and chaining works there always the possibility that a key or index does not exist in the data, and the proceeding method calls cause a nil pointer error and the program would ungracefully crash!

There are two option:

  • one is to check the return values for each method call but this defeats the point of chaining the function calls.
	//Get an array that does not exist
	chain_item = chain_error.GetMapItem("data")
	if chain_item ==nil{
		return fmt.Errorf("Missing Map item")
	}
	chain_item=chain_item.GetMapItem("arrays_does_not_exists")
	if chain_item ==nil{
		return fmt.Errorf("Missing Map item")
	}

  • Set the safe to true on the *CreateDataChain(value interface{},safe bool) Data function.

What this does is make the chain always return a Data object even if the key does not exist. this will stop the chain crashing and allow you to check for errors.

This comes with a Caveat you can only use the following functions to navigate the chain

  • GetMapItem
  • GetArrayItem
  • GetArrayCount

Not

  • ToArray
  • ToMap
	//Get an array that does not exist
	chain_item = chain_error.GetMapItem("data").GetMapItem("arrays_does_not_exists")
	if chain_item.Err != nil {
		//does not matter if you check the error on
		//chain_item or chain_error they both return the same error
		fmt.Printf("there was an error :%v \n", chain_error.Err)
		return fmt.Errorf("chain_item there was an error :%v \n", chain_item.Err)
	}


Examples

1. Read yaml and navigate the data
Example yaml data:

data:
  arrays:
    - "array_string_1"
    - "array_string_2"
    - "array_string_3"
  maps:
    map_string_1: "map_string_1"
    map_string_2: "map_string_2"
    map_string_3: "map_string_3"
  convert_bool:
    string_bool_true: "true"
    string_bool_false: "false"
    string_bool_y: "y"
    string_bool_n: "n"
    string_bool_1: "1"
    string_bool_0: "0"
    string_bool_yes: "yes"
    string_bool_no: "no"
    string_bool_pass: "pass"
    string_bool_fail: "fail"
  convert_int:
    float_int: 1.56
    string_int: "2"
    int_int: 3
    bool_int_true: true
    bool_int_false: false
  convert_float:
    float_float: 1.56
    string_float: "1.56"
    int_float: 5
    bool_float_true: true
    bool_float_false: false
  convert_string:
    float_string: 1.56
    string_string: "string"
    int_string: 5
    bool_string_true: true
    bool_string_false: false
  convert_map:
  

code example:
package main

import (
	"fmt"
	"io/ioutil"

	go_data_chain "github.com/Mrpye/go-data-chain"
	"gopkg.in/yaml.v3"
)

func main() {
	//*******************
	// Store example data
	//*******************
	var test_data interface{}

	//******************************
	//Read the example data from a file
	//******************************
	file, err := ioutil.ReadFile("example_data.yaml")
	if err != nil {
		panic(err)
	}
	err = yaml.Unmarshal([]byte(file), &test_data)
	if err != nil {
		panic(err)
	}
	//***********************************
	//Create an instance if go_data_chain
	//***********************************
	chain := go_data_chain.CreateDataChain(test_data, false)

	//*****************
	//Navigate the data
	//*****************

	//get string data from a map map_string_1
	chain_item := chain.GetMapItem("data").GetMapItem("maps")     //get a map item
	fmt.Println(chain_item.GetMapItem("map_string_1").ToString()) //cast as a string
	//Loop through an array
	chain_item = chain.GetMapItem("data").GetMapItem("arrays") //get a map item
	for i := 0; i < chain_item.GetArrayCount(); i++ {
		fmt.Println(chain_item.GetArrayItem(i).ToString())
		fmt.Println(chain_item.ToArray()[i].ToString())
	}

	//get bool data from a map convert_bool
	chain_item = chain.GetMapItem("data").GetMapItem("convert_bool") //get a map item
	fmt.Println(chain_item.GetMapItem("string_bool_true").ToBool())  //convert "true" to true
	fmt.Println(chain_item.GetMapItem("string_bool_no").ToBool())    //convert "no" to false

	//get int data from a map convert_int
	chain_item = chain.GetMapItem("data").GetMapItem("convert_int") //get a map item
	fmt.Println(chain_item.GetMapItem("float_int").ToInt64())       //convert 1.56 to 1
	fmt.Println(chain_item.GetMapItem("bool_int_true").ToInt8())    //convert true to 1

	//get float data from a map convert_float
	chain_item = chain.GetMapItem("data").GetMapItem("convert_float") //get a map item
	fmt.Println(chain_item.GetMapItem("float_float").ToFloat64())     //convert 1.56 to 1
	fmt.Println(chain_item.GetMapItem("float_float").ToFloat32())     //convert true to 1

	//get string data from a map convert_string
	chain_item = chain.GetMapItem("data").GetMapItem("convert_string") //get a map item
	fmt.Println(chain_item.GetMapItem("int_string").ToString())        //convert 1.56 to 1
	fmt.Println(chain_item.GetMapItem("string_string").ToString())     //convert true to 1

	//*****************************************************************************************
	// Create an instance if go_data_chain but with safe parameter to true
	// This will always return a chain item even if the data does not exist
	// For this to work you must use the GetMapItem(), GetArrayItem() and GetArrayCount methods
	// And check the Err property of the chain item for errors
	// This is a workaround so that if data does not exist the program does not crash
	// And give you the option to handle the error
	//*****************************************************************************************
	chain_error := go_data_chain.CreateDataChain(test_data, true)

	//***********************************************
	//get string data from a map maps_does_not_exists
	//***********************************************
	chain_item = chain_error.GetMapItem("data").GetMapItem("maps_does_not_exists") //get a map item
	fmt.Println(chain_item.GetMapItem("map_string_1").ToString())                  //cast as a string
	if chain_error.Err != nil {
		fmt.Printf("there was an error for GetMapItem:%v \n", chain_error.Err)
		chain_error.Err = nil //reset the error
	}

	//********************************
	//Get an array that does not exist
	//********************************
	chain_item = chain_error.GetMapItem("data").GetMapItem("arrays_does_not_exists") //get a map item
	if chain_error.Err != nil {
		fmt.Printf("there was an error for GetMapItem:%v \n", chain_error.Err)
	}
	//****************************************
	//Because the array does not exist
	//The GetArrayCount() method will return 0
	// And return an error
	//****************************************
	for i := 0; i < chain_item.GetArrayCount(); i++ {
		fmt.Println(chain_item.GetArrayItem(i).ToString())
		fmt.Println(chain_item.ToArray()[i].ToString())
	}
	if chain_error.Err != nil {
		fmt.Printf("there was an error GetArrayCount:%v \n", chain_error.Err)
	}

}


Result:
map_string_1
array_string_1
array_string_1
array_string_2
array_string_2
array_string_3
array_string_3
true
false
1
1
1.56
1.56
5
string

go-data-chain Methods

//Data type 
type Data

// CreateDynamicData creates a new Data object
// - value: the value to set
// - safe: makes the chain always return a empty data
CreateDataChain(value interface{},safe bool) *Data

// GetArrayItem returns an item from the array
// - index: the index of the item to get
GetArrayItem(index int) *Data

// GetArrayCount returns the number of items in the array
GetArrayCount() int

// ToArray returns an array of Data objects
ToArray() []Data

// ToMap returns a map of Data objects
ToMap() map[string]Data

// GetMapItem a Data object
// - Key: the key to get
GetMapItem(key string) *Data

// GetInterface returns the data as an interface{}
GetInterface() interface{}

// GetType returns the type of the data as a string
GetType() string

// ToString returns the data as a string
ToString() string

// ToBool returns the data as a bool
ToBool() bool 

// ToFloat32 returns the data as a float32
ToFloat32() float32

// ToFloat64 returns the data as a float64
ToFloat64() float64

// ToInt returns the data as an int
ToInt() int 

// ToInt8 returns the data as an int8
ToInt8() int8

// ToInt32 returns the data as an int32
ToInt32() int32

// ToInt64 returns the data as an int64
ToInt64() int64

Todo:

  • Look at a way to handle errors

Change Log

v0.1.0
  • First build
v0.2.0
  • Added a way to handle nil pointer crash when map key or array index is not found.

license

go-data-chain is Apache 2.0 licensed.

Documentation

Overview

Package to allow navigation of inteface{} data types in a generic way with auto conversion to the correct type where possible

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Data

type Data struct {
	Err error
	// contains filtered or unexported fields
}

Data is a struct that can hold any type of data

func CreateDataChain

func CreateDataChain(value interface{}, safe bool) *Data

CreateDynamicData creates a new Data object - value: the value to set - safe: if true the chain will not crash if the data does not exist

func (*Data) GetArrayCount

func (m *Data) GetArrayCount() int

GetArrayCount returns the number of items in the array

func (*Data) GetArrayItem

func (m *Data) GetArrayItem(index int) *Data

GetArrayItem returns an item from the array - index: the index of the item to get

func (*Data) GetMapItem

func (m *Data) GetMapItem(key string) *Data

GetMapItem gets a map item by key - Key: the key to get returns a Data object if the key exists or nil if it does not

func (*Data) GetType

func (m *Data) GetType() string

GetType returns the type of the data as a string

func (*Data) ToArray added in v0.2.0

func (m *Data) ToArray() []Data

ToArray returns the data as an array

func (*Data) ToBool

func (m *Data) ToBool() bool

ToBool returns the data as a bool

func (*Data) ToFloat32

func (m *Data) ToFloat32() float32

ToFloat32 returns the data as a float32

func (*Data) ToFloat64

func (m *Data) ToFloat64() float64

ToFloat64 returns the data as a float64

func (*Data) ToInt

func (m *Data) ToInt() int

ToInt returns the data as an int

func (*Data) ToInt32

func (m *Data) ToInt32() int32

ToInt32 returns the data as an int32

func (*Data) ToInt64

func (m *Data) ToInt64() int64

ToInt64 returns the data as an int64

func (*Data) ToInt8

func (m *Data) ToInt8() int8

ToInt8 returns the data as an int8

func (*Data) ToInterface added in v0.2.0

func (m *Data) ToInterface() interface{}

ToInterface returns the data as an interface{}

func (*Data) ToMap added in v0.2.0

func (m *Data) ToMap() map[string]Data

ToMap returns the data as a map

func (*Data) ToString

func (m *Data) ToString() string

ToString returns the data as a string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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