| // Copyright 2019 The etcd Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package client |
| |
| import ( |
| "github.com/json-iterator/go" |
| "github.com/modern-go/reflect2" |
| "strconv" |
| "unsafe" |
| ) |
| |
| type customNumberExtension struct { |
| jsoniter.DummyExtension |
| } |
| |
| func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder { |
| if typ.String() == "interface {}" { |
| return customNumberDecoder{} |
| } |
| return nil |
| } |
| |
| type customNumberDecoder struct { |
| } |
| |
| func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { |
| switch iter.WhatIsNext() { |
| case jsoniter.NumberValue: |
| var number jsoniter.Number |
| iter.ReadVal(&number) |
| i64, err := strconv.ParseInt(string(number), 10, 64) |
| if err == nil { |
| *(*interface{})(ptr) = i64 |
| return |
| } |
| f64, err := strconv.ParseFloat(string(number), 64) |
| if err == nil { |
| *(*interface{})(ptr) = f64 |
| return |
| } |
| iter.ReportError("DecodeNumber", err.Error()) |
| default: |
| *(*interface{})(ptr) = iter.Read() |
| } |
| } |
| |
| // caseSensitiveJsonIterator returns a jsoniterator API that's configured to be |
| // case-sensitive when unmarshalling, and otherwise compatible with |
| // the encoding/json standard library. |
| func caseSensitiveJsonIterator() jsoniter.API { |
| config := jsoniter.Config{ |
| EscapeHTML: true, |
| SortMapKeys: true, |
| ValidateJsonRawMessage: true, |
| CaseSensitive: true, |
| }.Froze() |
| // Force jsoniter to decode number to interface{} via int64/float64, if possible. |
| config.RegisterExtension(&customNumberExtension{}) |
| return config |
| } |