// Copyright 2016 Qiang Xue. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package validation import ( "encoding/json" "fmt" "sort" ) type ( // Errors represents the validation errors that are indexed by struct field names, map or slice keys. Errors map[string]error // InternalError represents an error that should NOT be treated as a validation error. InternalError interface { error InternalError() error } internalError struct { error } ) // NewInternalError wraps a given error into an InternalError. func NewInternalError(err error) InternalError { return &internalError{error: err} } // InternalError returns the actual error that it wraps around. func (e *internalError) InternalError() error { return e.error } // Error returns the error string of Errors. func (es Errors) Error() string { if len(es) == 0 { return "" } keys := []string{} for key := range es { keys = append(keys, key) } sort.Strings(keys) s := "" for i, key := range keys { if i > 0 { s += "; " } if errs, ok := es[key].(Errors); ok { s += fmt.Sprintf("%v: (%v)", key, errs) } else { s += fmt.Sprintf("%v: %v", key, es[key].Error()) } } return s + "." } // MarshalJSON converts the Errors into a valid JSON. func (es Errors) MarshalJSON() ([]byte, error) { errs := map[string]interface{}{} for key, err := range es { if ms, ok := err.(json.Marshaler); ok { errs[key] = ms } else { errs[key] = err.Error() } } return json.Marshal(errs) } // Filter removes all nils from Errors and returns back the updated Errors as an error. // If the length of Errors becomes 0, it will return nil. func (es Errors) Filter() error { for key, value := range es { if value == nil { delete(es, key) } } if len(es) == 0 { return nil } return es }