blob: 97cdbcd7cfa57d7960a93f76f51b1a0931917984 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001// Copyright 2019 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package client
16
17import (
18 "github.com/json-iterator/go"
19 "github.com/modern-go/reflect2"
20 "strconv"
21 "unsafe"
22)
23
24type customNumberExtension struct {
25 jsoniter.DummyExtension
26}
27
28func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
29 if typ.String() == "interface {}" {
30 return customNumberDecoder{}
31 }
32 return nil
33}
34
35type customNumberDecoder struct {
36}
37
38func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
39 switch iter.WhatIsNext() {
40 case jsoniter.NumberValue:
41 var number jsoniter.Number
42 iter.ReadVal(&number)
43 i64, err := strconv.ParseInt(string(number), 10, 64)
44 if err == nil {
45 *(*interface{})(ptr) = i64
46 return
47 }
48 f64, err := strconv.ParseFloat(string(number), 64)
49 if err == nil {
50 *(*interface{})(ptr) = f64
51 return
52 }
53 iter.ReportError("DecodeNumber", err.Error())
54 default:
55 *(*interface{})(ptr) = iter.Read()
56 }
57}
58
59// caseSensitiveJsonIterator returns a jsoniterator API that's configured to be
60// case-sensitive when unmarshalling, and otherwise compatible with
61// the encoding/json standard library.
62func caseSensitiveJsonIterator() jsoniter.API {
63 config := jsoniter.Config{
64 EscapeHTML: true,
65 SortMapKeys: true,
66 ValidateJsonRawMessage: true,
67 CaseSensitive: true,
68 }.Froze()
69 // Force jsoniter to decode number to interface{} via int64/float64, if possible.
70 config.RegisterExtension(&customNumberExtension{})
71 return config
72}