Skip to content

Commit

Permalink
Merge pull request #116 from bitrise-io/feature/serialize-model-fix
Browse files Browse the repository at this point in the history
EnvsYMLModel -> EnvsSerializeModel ; EnvsSerializeModel.Normalize
  • Loading branch information
viktorbenei authored Dec 14, 2016
2 parents 8c4944e + a8b2f8f commit 0507a11
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 9 deletions.
2 changes: 1 addition & 1 deletion cli/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func envListSizeInBytes(envs []models.EnvironmentItemModel) (int, error) {

func validateEnv(key, value string, envList []models.EnvironmentItemModel) (string, error) {
if key == "" {
return "", errors.New("Key is not specified, required.")
return "", errors.New("Key is not specified, required")
}

configs, err := envman.GetConfigs()
Expand Down
10 changes: 5 additions & 5 deletions envman/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,18 @@ func removeDefaults(env *models.EnvironmentItemModel) error {
return nil
}

func generateFormattedYMLForEnvModels(envs []models.EnvironmentItemModel) (models.EnvsYMLModel, error) {
func generateFormattedYMLForEnvModels(envs []models.EnvironmentItemModel) (models.EnvsSerializeModel, error) {
envMapSlice := []models.EnvironmentItemModel{}
for _, env := range envs {
err := removeDefaults(&env)
if err != nil {
return models.EnvsYMLModel{}, err
return models.EnvsSerializeModel{}, err
}

hasOptions := false
opts, err := env.GetOptions()
if err != nil {
return models.EnvsYMLModel{}, err
return models.EnvsSerializeModel{}, err
}

if opts.Title != nil {
Expand Down Expand Up @@ -170,7 +170,7 @@ func generateFormattedYMLForEnvModels(envs []models.EnvironmentItemModel) (model
envMapSlice = append(envMapSlice, env)
}

return models.EnvsYMLModel{
return models.EnvsSerializeModel{
Envs: envMapSlice,
}, nil
}
Expand Down Expand Up @@ -212,7 +212,7 @@ func InitAtPath(pth string) error {

// ParseEnvsYML ...
func ParseEnvsYML(bytes []byte) ([]models.EnvironmentItemModel, error) {
var envsYML models.EnvsYMLModel
var envsYML models.EnvsSerializeModel
if err := yaml.Unmarshal(bytes, &envsYML); err != nil {
return []models.EnvironmentItemModel{}, err
}
Expand Down
6 changes: 3 additions & 3 deletions models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ type EnvironmentItemOptionsModel struct {
// EnvironmentItemModel ...
type EnvironmentItemModel map[string]interface{}

// EnvsYMLModel ...
type EnvsYMLModel struct {
Envs []EnvironmentItemModel `yaml:"envs"`
// EnvsSerializeModel ...
type EnvsSerializeModel struct {
Envs []EnvironmentItemModel `json:"envs",yaml:"envs"`
}

// EnvsJSONListModel ...
Expand Down
14 changes: 14 additions & 0 deletions models/models_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ func (env *EnvironmentItemModel) Normalize() error {
return nil
}

// Normalize - if successful this makes the model JSON serializable.
// Without this, if the object was created with e.g. a YAML parser,
// the type of `opts` might be map[interface]interface, which is not JSON serializable.
// After this call it's ensured that the type of objects is map[string]interface,
// which is JSON serializable.
func (envsSerializeObj *EnvsSerializeModel) Normalize() error {
for _, envObj := range envsSerializeObj.Envs {
if err := envObj.Normalize(); err != nil {
return err
}
}
return nil
}

// FillMissingDefaults ...
func (env *EnvironmentItemModel) FillMissingDefaults() error {
options, err := env.GetOptions()
Expand Down
34 changes: 34 additions & 0 deletions models/models_methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package models
import (
"testing"

yaml "gopkg.in/yaml.v2"

"encoding/json"

"github.com/bitrise-io/go-utils/pointers"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -359,3 +363,33 @@ func TestValidate(t *testing.T) {
}
require.NoError(t, env.Validate())
}

func Test_EnvsSerializeModel_Normalize(t *testing.T) {
yamlContent := `envs:
- KEY_ONE: first value
- KEY_TWO: second value, with options
opts:
is_expand: true
`
var objFromYAML EnvsSerializeModel
require.NoError(t, yaml.Unmarshal([]byte(yamlContent), &objFromYAML))

// the objFromYAML object in this state can't be serialized to JSON directly,
// as the YAML parser parses the `opts` into map[interface]interface,
// which is not supported by JSON
{
_, err := json.Marshal(objFromYAML)
require.EqualError(t, err, `json: unsupported type: map[interface {}]interface {}`)
}

// now, if we call Normalize on this object, that will convert the map[interface]interface
// into map[string]interface, which is JSON serializable
require.NoError(t, objFromYAML.Normalize())

// let's try the serialization again - this time it will work!
{
jsonContBytes, err := json.Marshal(objFromYAML)
require.NoError(t, err)
require.Equal(t, `{"envs":[{"KEY_ONE":"first value","opts":{}},{"KEY_TWO":"second value, with options","opts":{"is_expand":true}}]}`, string(jsonContBytes))
}
}

0 comments on commit 0507a11

Please sign in to comment.