-
Notifications
You must be signed in to change notification settings - Fork 6
/
conjson.go
138 lines (119 loc) · 4.83 KB
/
conjson.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Package conjson provides a simple, functional, no-tags-required mechanism to
// handle and transform JSON representations of values, consistently.
//
// The types in this package provide JSON Encoder and Decoder wrappers, along
// with Marshaler and Unmarshaler implementations, that allow for the
// transformation of the JSON data that is used in those mechanisms.
//
// The examples may provide more obvious context and reasoning for the use of
// these transformations.
//
// Copyright © Trevor N. Suarez (Rican7)
package conjson
import (
"encoding/json"
"github.com/Rican7/conjson/transform"
)
// Encoder is an interface defining a simple JSON encoder, with an interface
// compatible with `encoding/json.Encoder`.
type Encoder interface {
// Encode takes a value and encodes the JSON representation of that value to
// the underlying/inner encoder.
//
// See the documentation for both `encoding/json.Encoder` and
// `encoding/json.Marshal` for more details about the workings of the
// underlying encoder.
Encode(interface{}) error
}
// Decoder is an interface defining a simple JSON decoder, with an interface
// compatible with `encoding/json.Decoder`.
type Decoder interface {
// Decode reads the next JSON represented value from the underlying/inner
// decoder and stores the decoded result in the pointed to passed value.
//
// See the documentation for both `encoding/json.Decoder` and
// `encoding/json.Unmarshal` for more details about the workings of the
// underlying decoder.
Decode(interface{}) error
}
// marshaler is a structure that wraps a value and a list of transformers to
// enable JSON marshaling with output transformations.
type marshaler struct {
value interface{}
transformers []transform.Transformer
}
// unmarshaler is a structure that wraps a value and a list of transformers to
// enable JSON unmarshaling with input transformations.
type unmarshaler struct {
value interface{}
transformers []transform.Transformer
}
// encoder is a structure that wraps an `encoding/json.Encoder` and a list
// of transformers to enable JSON encoding with output transformations.
type encoder struct {
inner *json.Encoder
transformers []transform.Transformer
}
// decoder is a structure that wraps an `encoding/json.Decoder` and a list
// of transformers to enable JSON decoding with input transformations.
type decoder struct {
inner *json.Decoder
transformers []transform.Transformer
}
// NewMarshaler takes a value and a variable number of `transform.Transformer`s
// and returns an `encoding/json.Marshaler` that runs the given transformers
// upon JSON marshaling.
//
// See the documentation for both `encoding/json.Marshaler` and
// `encoding/json.Marshal` for more details about JSON marshaling.
func NewMarshaler(value interface{}, transformers ...transform.Transformer) json.Marshaler {
return &marshaler{value, transformers}
}
// NewUnmarshaler takes a pointer value and a variable number of
// `transform.Transformer`s and returns an `encoding/json.Unmarshaler` that runs
// the given transformers upon JSON unmarshaling.
//
// See the documentation for both `encoding/json.Unmarshaler` and
// `encoding/json.Unmarshal` for more details about JSON unmarshaling.
func NewUnmarshaler(value interface{}, transformers ...transform.Transformer) json.Unmarshaler {
return &unmarshaler{value, transformers}
}
// NewEncoder takes an `encoding/json.Encoder` and a variable number of
// `transform.Transformer`s and returns an `Encoder` that runs the given
// transformers upon JSON encoding.
//
// See the documentation for both `encoding/json.Encoder` and
// `encoding/json.Marshal` for more details about the passed inner encoder.
func NewEncoder(inner *json.Encoder, transformers ...transform.Transformer) Encoder {
return &encoder{inner, transformers}
}
// NewDecoder takes an `encoding/json.Decoder` and a variable number of
// `transform.Transformer`s and returns an `Decoder` that runs the given
// transformers upon JSON encoding.
//
// See the documentation for both `encoding/json.Decoder` and
// `encoding/json.Unmarshal` for more details about the passed inner decoder.
func NewDecoder(inner *json.Decoder, transformers ...transform.Transformer) Decoder {
return &decoder{inner, transformers}
}
func (m *marshaler) MarshalJSON() ([]byte, error) {
marshalled, err := json.Marshal(m.value)
if nil == err {
marshalled = transform.Bytes(marshalled, transform.Marshal, m.transformers...)
}
return marshalled, err
}
func (um *unmarshaler) UnmarshalJSON(data []byte) error {
data = transform.Bytes(data, transform.Unmarshal, um.transformers...)
return json.Unmarshal(data, um.value)
}
func (e *encoder) Encode(value interface{}) error {
return e.inner.Encode(
NewMarshaler(value, e.transformers...),
)
}
func (e *decoder) Decode(value interface{}) error {
return e.inner.Decode(
NewUnmarshaler(value, e.transformers...),
)
}