-
Notifications
You must be signed in to change notification settings - Fork 0
/
encoding.go
86 lines (73 loc) · 1.93 KB
/
encoding.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
package httpjson
import (
"encoding/json"
"github.com/diamcircle/go/support/errors"
)
// ErrNotJSONObject is returned when Object.UnmarshalJSON is called
// with bytes not representing a valid json object.
// A valid json object means it starts with `null` or `{`, not `[`.
var ErrNotJSONObject = errors.New("input is not a json object")
// RawObject can be used directly to make sure that what's in the request body
// is not a json array:
//
// func example(ctx context.Context, in httpjson.RawObject)
//
// It can also be used as a field in a struct:
//
// type example struct {
// name string
// extra httpjson.RawObject
// }
//
// In this case, Unmarshaler will check whether extra is a json object ot not.
// It will error if extra is a json number/string/array/boolean.
//
// RawObject also implements Marshaler so that we would populate an empty json
// object is extra is not set.
type RawObject []byte
func (o RawObject) MarshalJSON() ([]byte, error) {
if len(o) == 0 {
return []byte("{}"), nil
}
return o, nil
}
func (o *RawObject) UnmarshalJSON(in []byte) error {
var first byte
for _, c := range in {
if !isSpace(c) {
first = c
break
}
}
// input does not start with 'n' ("null") or '{'
if first != 'n' && first != '{' {
return ErrNotJSONObject
}
*o = in
return nil
}
// https://github.com/golang/go/blob/9f193fbe31d7ffa5f6e71a6387cbcf4636306660/src/encoding/json/scanner.go#L160-L162
func isSpace(c byte) bool {
return c == ' ' || c == '\t' || c == '\r' || c == '\n'
}
// This type is used to tell whether a JSON key is presented with its value
// being a JSON null value or is not presented.
type OptString struct {
Value string
Valid bool
IsSet bool
}
func (s *OptString) UnmarshalJSON(in []byte) error {
s.IsSet = true
if string(in) == "null" {
s.Valid = false
return nil
}
var val string
if err := json.Unmarshal(in, &val); err != nil {
return err
}
s.Value = val
s.Valid = true
return nil
}