github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/json/config.go (about) 1 // Copyright 2022 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package json 12 13 import ( 14 "github.com/cockroachdb/cockroachdb-parser/pkg/util" 15 "github.com/cockroachdb/errors" 16 ) 17 18 // ParseOption is an option for JSON parsing. 19 type ParseOption interface { 20 apply(cfg *parseConfig) 21 } 22 23 // WithUnorderedObjectKeys returns an option that leaves JSON 24 // object keys unordered. 25 func WithUnorderedObjectKeys() ParseOption { 26 return funcOpt(func(cfg *parseConfig) { 27 cfg.unordered = true 28 }) 29 } 30 31 // WithGoStandardParser returns an option that forces the use of Go parser 32 // (encoding/json). 33 func WithGoStandardParser() ParseOption { 34 return funcOpt(func(cfg *parseConfig) { 35 cfg.impl = useStdGoJSON 36 }) 37 } 38 39 // WithFastJSONParser returns an option that forces the use of fast json parser. 40 func WithFastJSONParser() ParseOption { 41 return funcOpt(func(cfg *parseConfig) { 42 cfg.impl = useFastJSONParser 43 }) 44 } 45 46 // parseJSONImplType is the implementation library 47 // used to parse JSON. 48 type parseJSONImplType int 49 50 const ( 51 // useStdGoJSON : encoding/json 52 useStdGoJSON parseJSONImplType = iota 53 // useFastJSONParser : uses fast JSON parser (built on top of pkg/json high performance library) 54 useFastJSONParser 55 56 // Note: Other libraries tested and rejected include: 57 // * json-iter: A fine library; however, fastJSONParser consistently 58 // performed better, with much better memory allocation behavior. 59 // * go-json: universally slower, worse (allocation) than either 60 // standard or json-iter for larger inputs. 61 // * simdjson-go: too restrictive; doesn't work on all platforms, 62 // does not parse raw json literals (true/false, etc); and is not 63 // a drop in replacement. 64 // * ffjson, easyjson: not appropriate since these library use code 65 // generation, and cannot parse arbitrary JSON. 66 ) 67 68 // default configuration for parsing JSON. 69 var parseJSONDefaultConfig = func() (cfg parseConfig) { 70 cfg.impl = util.ConstantWithMetamorphicTestChoice( 71 "parse-json-impl", useFastJSONParser, useStdGoJSON, 72 ).(parseJSONImplType) 73 return cfg 74 }() 75 76 type parseConfig struct { 77 unordered bool 78 impl parseJSONImplType 79 } 80 81 func (c parseConfig) parseJSON(s string) (JSON, error) { 82 switch c.impl { 83 case useStdGoJSON: 84 return parseJSONGoStd(s, c) 85 case useFastJSONParser: 86 return parseUsingFastParser(s, c) 87 default: 88 return nil, errors.AssertionFailedf("invalid ParseJSON implementation %v", c.impl) 89 } 90 } 91 92 type funcOpt func(cfg *parseConfig) 93 94 func (f funcOpt) apply(cfg *parseConfig) { 95 f(cfg) 96 }