Skip to content

Commit

Permalink
Merge pull request #29 from fredbi/fix-marshaljson
Browse files Browse the repository at this point in the history
Fix marshaljson
  • Loading branch information
fredbi authored Feb 7, 2021
2 parents 1896884 + c694523 commit 8b5b779
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ linters:
- nestif
- godot
- errorlint
- paralleltest
- tparallel
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# OpenAPI errors [![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors) [![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
# OpenAPI errors

[![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors)
[![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors)
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/go-openapi/errors?status.svg)](http://godoc.org/github.com/go-openapi/errors)
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/errors.svg)](https://pkg.go.dev/github.com/go-openapi/errors)
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/errors.svg)](https://golangci.com)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/errors)](https://goreportcard.com/report/github.com/go-openapi/errors)

Expand Down
17 changes: 17 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ func (a *apiError) Code() int32 {
return a.code
}

// MarshalJSON implements the JSON encoding interface
func (a apiError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": a.code,
"message": a.message,
})
}

// New creates a new API error with a code and a message
func New(code int32, message string, args ...interface{}) Error {
if len(args) > 0 {
Expand Down Expand Up @@ -81,6 +89,15 @@ func (m *MethodNotAllowedError) Code() int32 {
return m.code
}

// MarshalJSON implements the JSON encoding interface
func (m MethodNotAllowedError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": m.code,
"message": m.message,
"allowed": m.Allowed,
})
}

func errorAsJSON(err Error) []byte {
b, _ := json.Marshal(struct {
Code int32 `json:"code"`
Expand Down
43 changes: 43 additions & 0 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type customError struct {
Expand Down Expand Up @@ -206,3 +208,44 @@ func TestValidateName(t *testing.T) {
assert.EqualValues(t, "myNewName", vv.Name)
assert.EqualValues(t, "myNewNamemyMessage", vv.message)
}

func TestMarshalJSON(t *testing.T) {
const (
expectedCode = http.StatusUnsupportedMediaType
value = "myValue"
)
list := []string{"a", "b"}

e := InvalidContentType(value, list)

jazon, err := e.MarshalJSON()
require.NoError(t, err)

expectedMessage := strings.ReplaceAll(fmt.Sprintf(contentTypeFail, value, list), `"`, `\"`)

expectedJSON := fmt.Sprintf(
`{"code":%d,"message":"%s","name":"Content-Type","in":"header","value":"%s","values":["a","b"]}`,
expectedCode, expectedMessage, value,
)
assert.JSONEq(t, expectedJSON, string(jazon))

a := apiError{code: 1, message: "a"}
jazon, err = a.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"a"}`, string(jazon))

m := MethodNotAllowedError{code: 1, message: "a", Allowed: []string{"POST"}}
jazon, err = m.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"a","allowed":["POST"]}`, string(jazon))

c := CompositeError{Errors: []error{e}, code: 1, message: "a"}
jazon, err = c.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, fmt.Sprintf(`{"code":1,"message":"a","errors":[%s]}`, expectedJSON), string(jazon))

p := ParseError{code: 1, message: "x", Name: "a", In: "b", Value: "c", Reason: fmt.Errorf("d")}
jazon, err = p.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"x","name":"a","in":"b","value":"c","reason":"d"}`, string(jazon))
}
13 changes: 13 additions & 0 deletions headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package errors

import (
"encoding/json"
"fmt"
"net/http"
)
Expand All @@ -38,6 +39,18 @@ func (e *Validation) Code() int32 {
return e.code
}

// MarshalJSON implements the JSON encoding interface
func (e Validation) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": e.code,
"message": e.message,
"in": e.In,
"name": e.Name,
"value": e.Value,
"values": e.Values,
})
}

// ValidateName produces an error message name for an aliased property
func (e *Validation) ValidateName(name string) *Validation {
if e.Name == "" && name != "" {
Expand Down
6 changes: 3 additions & 3 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (
// APIVerificationFailed is an error that contains all the missing info for a mismatched section
// between the api registrations and the api spec
type APIVerificationFailed struct {
Section string
MissingSpecification []string
MissingRegistration []string
Section string `json:"section,omitempty"`
MissingSpecification []string `json:"missingSpecification,omitempty"`
MissingRegistration []string `json:"missingRegistration,omitempty"`
}

//
Expand Down
21 changes: 20 additions & 1 deletion parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

package errors

import "fmt"
import (
"encoding/json"
"fmt"
)

// ParseError represents a parsing error
type ParseError struct {
Expand All @@ -35,6 +38,22 @@ func (e *ParseError) Code() int32 {
return e.code
}

// MarshalJSON implements the JSON encoding interface
func (e ParseError) MarshalJSON() ([]byte, error) {
var reason string
if e.Reason != nil {
reason = e.Reason.Error()
}
return json.Marshal(map[string]interface{}{
"code": e.code,
"message": e.message,
"in": e.In,
"name": e.Name,
"value": e.Value,
"reason": reason,
})
}

const (
parseErrorTemplContent = `parsing %s %s from %q failed, because %s`
parseErrorTemplContentNoIn = `parsing %s from %q failed, because %s`
Expand Down
10 changes: 10 additions & 0 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package errors

import (
"encoding/json"
"fmt"
"strings"
)
Expand Down Expand Up @@ -119,6 +120,15 @@ func (c *CompositeError) Error() string {
return c.message
}

// MarshalJSON implements the JSON encoding interface
func (c CompositeError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": c.code,
"message": c.message,
"errors": c.Errors,
})
}

// CompositeValidationError an error to wrap a bunch of other errors
func CompositeValidationError(errors ...error) *CompositeError {
return &CompositeError{
Expand Down

0 comments on commit 8b5b779

Please sign in to comment.