635 lines
22 KiB
Go
635 lines
22 KiB
Go
package jsonvalue
|
||
|
||
import "github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
|
||
|
||
const (
|
||
initialArrayCapacity = 32
|
||
asciiSize = 128
|
||
)
|
||
|
||
// Deprecated: Opt is the option of jsonvalue in marshaling. This type is deprecated,
|
||
// please use OptXxxx() functions instead.
|
||
//
|
||
// Opt 表示序列化当前 jsonvalue 类型时的参数。这个类型后续可能不再迭代新字段了,请改用 OptXxxx() 函数进行配置。
|
||
type Opt struct {
|
||
// OmitNull tells how to handle null json value. The default value is false.
|
||
// If OmitNull is true, null value will be omitted when marshaling.
|
||
//
|
||
// OmitNull 表示是否忽略 JSON 中的 null 类型值。默认为 false.
|
||
OmitNull bool
|
||
|
||
// ignoreJsonOmitempty ignore json tag "omitempty", which means that every data
|
||
// would be parsed into *jsonvalue.V
|
||
ignoreJsonOmitempty bool
|
||
|
||
// MarshalLessFunc is used to handle sequences of marshaling. Since object is
|
||
// implemented by hash map, the sequence of keys is unexpectable. For situations
|
||
// those need settled JSON key-value sequence, please use MarshalLessFunc.
|
||
//
|
||
// Note: Elements in an array value would NOT trigger this function as they are
|
||
// already sorted.
|
||
//
|
||
// We provides a example DefaultStringSequence. It is quite useful when calculating
|
||
// idempotence of a JSON text, as key-value sequences should be fixed.
|
||
//
|
||
// MarshalLessFunc 用于处理序列化 JSON 对象类型时,键值对的顺序。由于 object 类型是采用 go
|
||
// 原生的 map 类型,采用哈希算法实现,
|
||
// 因此其键值对的顺序是不可控的。而为了提高效率,jsonvalue 的内部实现中并不会刻意保存键值对的顺序。
|
||
// 如果有必要在序列化时固定键值对顺序的话,
|
||
// 可以使用这个函数。
|
||
//
|
||
// 注意:array 类型中键值对的顺序不受这个函数的影响
|
||
//
|
||
// 此外,我们提供了一个例子: DefaultStringSequence。当需要计算 JSON 文本的幂等值时,
|
||
// 由于需要不变的键值对顺序,因此这个函数是非常有用的。
|
||
MarshalLessFunc MarshalLessFunc
|
||
|
||
// MarshalKeySequence is used to handle sequance of marshaling. This is much simpler
|
||
// than MarshalLessFunc, just pass a string slice identifying key sequence. For keys
|
||
// those are not in this slice, they would be appended in the end according to result
|
||
// of Go string comparing. Therefore this parameter is useful for ensure idempotence.
|
||
//
|
||
// MarshalKeySequence 也用于处理序列化时的键值对顺序。与 MarshalLessFunc 不同,这个只需要用字符串
|
||
// 切片的形式指定键的顺序即可,实现上更为简易和直观。对于那些不在指定切片中的键,那么将会统一放在结尾,
|
||
// 并且按照 go 字符串对比的结果排序。也可以保证幂等。
|
||
MarshalKeySequence []string
|
||
keySequence map[string]int // generated from MarshalKeySequence
|
||
|
||
// marshalBySetSequence enables object key sequence by when it is set.
|
||
//
|
||
// 按照 key 被设置的顺序处理序列化时的 marshal 顺序
|
||
marshalBySetSequence bool
|
||
|
||
// FloatNaNHandleType tells what to deal with float NaN.
|
||
//
|
||
// FloatNaNHandleType 表示当处理 float 的时候,如果遇到了 NaN 的话,要如何处理。
|
||
FloatNaNHandleType FloatNaNHandleType
|
||
// FloatNaNToString works with FloatNaNHandleType = FloatNaNConvertToString. It tells
|
||
// what string to replace to with NaN. If not specified, NaN will be set as string "NaN".
|
||
//
|
||
// FloatNaNToString 搭配 FloatNaNHandleType = FloatNaNConvertToString 使用,表示将 NaN
|
||
// 映射为哪个字符串。这个值如果不指定,则默认会被设置为字符串 "NaN"
|
||
FloatNaNToString string
|
||
// FloatNaNToFloat works with FloatNaNHandleType = FloatNaNConvertToFloat. It tells
|
||
// what float number will be mapped to as for NaN. NaN, +Inf or -Inf are not allowed
|
||
// for this option.
|
||
//
|
||
// FloatNaNToFloat 搭配 FloatNaNHandleType = FloatNaNConvertToFloat 使用,表示将 NaN
|
||
// 映射为哪个 float64 值。不允许指定为 NaN, +Inf 或 -Inf。如果不指定,则映射为 0。
|
||
FloatNaNToFloat float64
|
||
|
||
// FloatInfHandleType tells what to deal with float +Inf and -Inf.
|
||
//
|
||
// FloatInfHandleType 表示当处理 float 的时候,如果遇到了 +Inf 和 -Inf 的话,要如何处理。
|
||
FloatInfHandleType FloatInfHandleType
|
||
// FloatInfPositiveToString works with FloatInfHandleType = FloatInfConvertToFloat.
|
||
// It tells what float number will be mapped to as for +Inf. If not specified, +Inf
|
||
// will be set as string "+Inf".
|
||
//
|
||
// FloatInfPositiveToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
|
||
// 表示将 NaN 映射为哪个字符串。
|
||
// 这个值如果不指定,则默认会被设置为字符串 "+Inf"
|
||
FloatInfPositiveToString string
|
||
// FloatInfNegativeToString works with FloatInfHandleType = FloatInfConvertToFloat.
|
||
// It tells what float number will be mapped to as for -Inf. If not specified, -Inf
|
||
// will be set as string "-" + strings.TrimLeft(FloatInfPositiveToString, "+").
|
||
//
|
||
// FloatInfNegativeToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
|
||
// 表示将 NaN 映射为哪个字符串。这个值如果不指定,则默认会被设置为字符串 "-" + strings.TrimLeft(FloatInfPositiveToString, "+")
|
||
FloatInfNegativeToString string
|
||
// FloatInfToFloat works with FloatInfHandleType = FloatInfConvertToFloat. It tells
|
||
// what float numbers will be mapped to as for +Inf. And -Inf will be specified as
|
||
// the negative value of this option. +Inf or -Inf are not allowed for this option.
|
||
//
|
||
// FloatInfToFloat 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,表示将 +Inf
|
||
// 映射为哪个 float64 值。而 -Inf 则会被映射为这个值的负数。不允许指定为 NaN, +Inf 或 -Inf。
|
||
// 如果不指定,则映射为 0
|
||
FloatInfToFloat float64
|
||
|
||
// unicodeEscapingFunc defines how to escaping a unicode greater than 0x7F to buffer.
|
||
unicodeEscapingFunc func(r rune, buf buffer.Buffer)
|
||
|
||
// asciiCharEscapingFunc defines how to marshal bytes lower than 0x80.
|
||
asciiCharEscapingFunc [asciiSize]func(b byte, buf buffer.Buffer)
|
||
|
||
// escProperties
|
||
escProperties escapingProperties
|
||
|
||
// indent
|
||
indent struct {
|
||
enabled bool
|
||
prefix string
|
||
indent string
|
||
cnt int
|
||
}
|
||
}
|
||
|
||
type FloatNaNHandleType uint8
|
||
|
||
const (
|
||
// FloatNaNTreatAsError indicates that error will be returned when a float number
|
||
// is NaN when marshaling.
|
||
//
|
||
// FloatNaNTreatAsError 表示当 marshal 遇到 NaN 时,返回错误。这是默认选项。
|
||
FloatNaNTreatAsError FloatNaNHandleType = 0
|
||
// FloatNaNConvertToFloat indicates that NaN will be replaced as another float
|
||
// number when marshaling. This option works with option FloatNaNToFloat.
|
||
//
|
||
// FloatNaNConvertToFloat 表示当 marshal 遇到 NaN 时,将值置为另一个数。搭配 FloatNaNToFloat
|
||
// 选项使用。
|
||
FloatNaNConvertToFloat FloatNaNHandleType = 1
|
||
// FloatNaNNull indicates that NaN key-value pair will be set as null when marshaling.
|
||
//
|
||
// FloatNaNNull 表示当 marshal 遇到 NaN 时,则将值设置为 null
|
||
FloatNaNNull FloatNaNHandleType = 2
|
||
// FloatNaNConvertToString indicates that NaN will be replaced as a string when
|
||
// marshaling. This option works with option FloatNaNToString.
|
||
//
|
||
// FloatNaNConvertToString 表示当 marshal 遇到 NaN 时,将值设置为一个字符串。搭配
|
||
// FloatNaNToString 选项使用。
|
||
FloatNaNConvertToString FloatNaNHandleType = 3
|
||
)
|
||
|
||
type FloatInfHandleType uint8
|
||
|
||
const (
|
||
// FloatInfTreatAsError indicates that error will be returned when a float number
|
||
// is Inf or -Inf when marshaling.
|
||
//
|
||
// FloatInfTreatAsError 表示当 marshal 遇到 Inf 或 -Inf 时,返回错误。这是默认选项。
|
||
FloatInfTreatAsError FloatInfHandleType = 0
|
||
// FloatInfConvertToFloat indicates that Inf and -Inf will be replaced as another
|
||
// float number when marshaling. This option works with option FloatInfToFloat.
|
||
//
|
||
// FloatInfConvertToFloat 表示当 marshal 遇到 Inf 或 -Inf 时,将值置为另一个数。搭配
|
||
// FloatInfToFloat 选项使用。
|
||
FloatInfConvertToFloat FloatInfHandleType = 1
|
||
// FloatInfNull indicates that Inf or -Inf key-value pair will be set as null
|
||
// when marshaling.
|
||
//
|
||
// FloatInfNull 表示当 marshal 遇到 Inf 和 -Inf 时,则将值设置为 null
|
||
FloatInfNull FloatInfHandleType = 2
|
||
// FloatInfConvertToString indicates that Inf anf -Inf will be replaced as a
|
||
// string when marshaling. This option works with option FloatInfPositiveToString
|
||
// and FloatInfNegativeToString.
|
||
//
|
||
// FloatInfConvertToString 表示当 marshal 遇到 Inf 和 -Inf 时,将值设置为一个字符串。
|
||
// 搭配 FloatInfPositiveToString FloatInfNegativeToString 选项使用。
|
||
FloatInfConvertToString FloatInfHandleType = 3
|
||
)
|
||
|
||
// Option is used for additional options when marshaling. Can be either a Opt{}
|
||
// (not pointer to it) or other options generated by jsonvalue.OptXxxx() functions.
|
||
//
|
||
// Option 表示用于序列化的额外选项。可以是一个 Opt{} 结构体值(而不是它的指针),或者是使用
|
||
// jsonvalue.OptXxxx() 函数生成的选项。
|
||
type Option interface {
|
||
mergeTo(*Opt)
|
||
}
|
||
|
||
func (o Opt) mergeTo(tgt *Opt) {
|
||
*tgt = o
|
||
}
|
||
|
||
// SetDefaultMarshalOptions set default option for marshaling. It is quite
|
||
// useful to invoke this function once in certern init funciton. Or you can
|
||
// invoke it after main entry. It is goroutine-safe.
|
||
//
|
||
// Please keep in mind that it takes effect globally and affects ALL marshaling
|
||
// behaviors in the future until the process ends. Please ensure that these
|
||
// options are acceptable for ALL future marshaling.
|
||
//
|
||
// However, you can still add additional options in later marshaling.
|
||
//
|
||
// SetDefaultMarshalOptions 设置序列化时的默认参数。使用方可以在 init 函数阶段,或者是
|
||
// main 函数启动后立刻调用该函数,以调整序列化时的默认行为。这个函数是协程安全的。
|
||
//
|
||
// 请记住,这个函数影响的是后续所有的序列化行为,请确保这个配置对后续的其他操作是可行的。
|
||
//
|
||
// 当然,你也可以在后续的操作中,基于原先配置的默认选项基础上,添加其他附加选项。
|
||
func SetDefaultMarshalOptions(opts ...Option) {
|
||
opt := emptyOptions()
|
||
opt.combineOptionsFrom(opts)
|
||
internal.defaultMarshalOption = opt
|
||
}
|
||
|
||
// ResetDefaultMarshalOptions reset default marshaling options to system default.
|
||
//
|
||
// ResetDefaultMarshalOptions 重设序列化时的默认选项为系统最原始的版本。
|
||
func ResetDefaultMarshalOptions() {
|
||
internal.defaultMarshalOption = emptyOptions()
|
||
}
|
||
|
||
func emptyOptions() *Opt {
|
||
return &Opt{}
|
||
}
|
||
|
||
func getDefaultOptions() *Opt {
|
||
res := *internal.defaultMarshalOption
|
||
return &res
|
||
}
|
||
|
||
func combineOptions(opts []Option) *Opt {
|
||
opt := getDefaultOptions()
|
||
opt.combineOptionsFrom(opts)
|
||
return opt
|
||
}
|
||
|
||
func (opt *Opt) combineOptionsFrom(opts []Option) {
|
||
for _, o := range opts {
|
||
o.mergeTo(opt)
|
||
}
|
||
opt.parseEscapingFuncs()
|
||
}
|
||
|
||
// ==== OmitNull ====
|
||
|
||
// OptOmitNull configures OmitNull field in Opt{}, identifying whether null values
|
||
// should be omitted when marshaling.
|
||
//
|
||
// OptOmitNull 配置 Opt{} 中的 OmitNull 字段,表示是否忽略 null 值。
|
||
func OptOmitNull(b bool) Option {
|
||
return &optOmitNull{b: b}
|
||
}
|
||
|
||
type optOmitNull struct {
|
||
b bool
|
||
}
|
||
|
||
func (o *optOmitNull) mergeTo(opt *Opt) {
|
||
opt.OmitNull = o.b
|
||
}
|
||
|
||
// ==== IgnoreOmitempty ====
|
||
|
||
// OptIgnoreOmitempty is used in Import() and New() function. This option tells
|
||
// jsonvalue to ignore json tag "omitempty", which means that every field would
|
||
// be parsed into *jsonvalue.V.
|
||
//
|
||
// OptIgnoreOmitempty 用在 Import 和 New() 函数中。这个选项将会忽略 json 标签中的
|
||
// "omitempty" 参数。换句话说, 所有的字段都会被解析并包装到 *jsonvalue.V 值中。
|
||
func OptIgnoreOmitempty() Option {
|
||
return optIgnoreOmitempty{}
|
||
}
|
||
|
||
type optIgnoreOmitempty struct{}
|
||
|
||
func (optIgnoreOmitempty) mergeTo(opt *Opt) {
|
||
opt.ignoreJsonOmitempty = true
|
||
}
|
||
|
||
// ==== MarshalLessFunc ===
|
||
|
||
// OptKeySequenceWithLessFunc configures MarshalLessFunc field in Opt{}, which defines
|
||
// key sequence when marshaling.
|
||
//
|
||
// OptKeySequenceWithLessFunc 配置 Opt{} 中的 MarshalLessFunc 字段,配置序列化时的键顺序。
|
||
func OptKeySequenceWithLessFunc(f MarshalLessFunc) Option {
|
||
return &optMarshalLessFunc{f: f}
|
||
}
|
||
|
||
// OptDefaultStringSequence configures MarshalLessFunc field in Opt{} as jsonvalue.DefaultStringSequence,
|
||
// which is dictionary sequence.
|
||
//
|
||
// OptDefaultStringSequence 配置 Opt{} 中的 MarshalLessFunc 字段为 jsonvalue.DefaultStringSequence,也就是字典序。
|
||
func OptDefaultStringSequence() Option {
|
||
return &optMarshalLessFunc{f: DefaultStringSequence}
|
||
}
|
||
|
||
type optMarshalLessFunc struct {
|
||
f MarshalLessFunc
|
||
}
|
||
|
||
func (o *optMarshalLessFunc) mergeTo(opt *Opt) {
|
||
if o.f != nil {
|
||
opt.MarshalLessFunc = o.f
|
||
opt.MarshalKeySequence = nil
|
||
opt.keySequence = nil
|
||
opt.marshalBySetSequence = false
|
||
}
|
||
}
|
||
|
||
// ==== MarshalKeySequence ====
|
||
|
||
// OptKeySequence configures MarshalKeySequence field in Opt{}.
|
||
//
|
||
// OptKeySequence 配置 Opt{} 中的 MarshalKeySequence 字段。
|
||
func OptKeySequence(seq []string) Option {
|
||
return &optMarshalKeySequence{seq: seq}
|
||
}
|
||
|
||
type optMarshalKeySequence struct {
|
||
seq []string
|
||
}
|
||
|
||
func (o *optMarshalKeySequence) mergeTo(opt *Opt) {
|
||
opt.MarshalLessFunc = nil
|
||
opt.MarshalKeySequence = o.seq
|
||
opt.keySequence = nil
|
||
opt.marshalBySetSequence = false
|
||
}
|
||
|
||
// ==== marshalBySetSequence ====
|
||
|
||
// OptSetSequence tells that when marshaling an object, the key will be sorted by
|
||
// the time they are added into or refreshed in its parent object. The later a key
|
||
//
|
||
// is set or updated, the later it and its value will be marshaled.
|
||
//
|
||
// OptSetSequence 指定在序列化 object 时,按照一个 key 被设置时的顺序进行序列化。如果一个
|
||
// key 越晚添加到 object 类型,则在序列化的时候越靠后。
|
||
func OptSetSequence() Option {
|
||
return optSetSequence{}
|
||
}
|
||
|
||
type optSetSequence struct{}
|
||
|
||
func (optSetSequence) mergeTo(opt *Opt) {
|
||
opt.MarshalLessFunc = nil
|
||
opt.MarshalKeySequence = nil
|
||
opt.keySequence = nil
|
||
opt.marshalBySetSequence = true
|
||
}
|
||
|
||
// ==== FloatNaNConvertToFloat ====
|
||
|
||
// OptFloatNaNToFloat tells that when marshaling float NaN, replace it as another
|
||
// valid float number.
|
||
//
|
||
// OptFloatNaNToFloat 指定当遇到 NaN 时,将值替换成一个有效的 float 值。
|
||
func OptFloatNaNToFloat(f float64) Option {
|
||
return &optFloatNaNConvertToFloat{f: f}
|
||
}
|
||
|
||
type optFloatNaNConvertToFloat struct {
|
||
f float64
|
||
}
|
||
|
||
func (o *optFloatNaNConvertToFloat) mergeTo(opt *Opt) {
|
||
opt.FloatNaNHandleType = FloatNaNConvertToFloat
|
||
opt.FloatNaNToFloat = o.f
|
||
}
|
||
|
||
// ==== FloatNaNNull ====
|
||
|
||
// OptFloatNaNToNull will replace a float value to null if it is NaN.
|
||
//
|
||
// OptFloatNaNToNull 表示当遇到 NaN 时,将值替换成 null
|
||
func OptFloatNaNToNull() Option {
|
||
return optFloatNaNNull{}
|
||
}
|
||
|
||
type optFloatNaNNull struct{}
|
||
|
||
func (optFloatNaNNull) mergeTo(opt *Opt) {
|
||
opt.FloatNaNHandleType = FloatNaNNull
|
||
}
|
||
|
||
// ==== FloatNaNConvertToString ====
|
||
|
||
// OptFloatNaNToStringNaN will replace a float value to string "NaN" if it is NaN.
|
||
//
|
||
// OptFloatNaNToStringNaN 表示遇到 NaN 时,将其替换成字符串 "NaN"
|
||
func OptFloatNaNToStringNaN() Option {
|
||
return &optFloatNaNConvertToString{s: "NaN"}
|
||
}
|
||
|
||
// OptFloatNaNToString will replace a float value to specified string if it is NaN.
|
||
// If empty string is given, will replace as "NaN".
|
||
//
|
||
// OptFloatNaNToString 表示当遇到 NaN 时,将其替换成指定的字符串。如果指定空字符串,则替换成 "NaN"
|
||
func OptFloatNaNToString(s string) Option {
|
||
return &optFloatNaNConvertToString{s: s}
|
||
}
|
||
|
||
type optFloatNaNConvertToString struct {
|
||
s string
|
||
}
|
||
|
||
func (o *optFloatNaNConvertToString) mergeTo(opt *Opt) {
|
||
opt.FloatNaNHandleType = FloatNaNConvertToString
|
||
opt.FloatNaNToString = o.s
|
||
}
|
||
|
||
// ==== FloatInfConvertToFloat ====
|
||
|
||
// OptFloatInfToFloat will replace a +Inf float value to specified f, while -f if
|
||
// the value is -Inf.
|
||
//
|
||
// OptFloatInfToFloat 表示当遇到 +Inf 时,将其替换成另一个 float 值;如果是 -Inf,则会替换成其取负数。
|
||
func OptFloatInfToFloat(f float64) Option {
|
||
return &optFloatInfConvertToFloat{f: f}
|
||
}
|
||
|
||
type optFloatInfConvertToFloat struct {
|
||
f float64
|
||
}
|
||
|
||
func (o *optFloatInfConvertToFloat) mergeTo(opt *Opt) {
|
||
opt.FloatInfHandleType = FloatInfConvertToFloat
|
||
opt.FloatInfToFloat = o.f
|
||
}
|
||
|
||
// ==== FloatInfNull ====
|
||
|
||
// OptFloatInfToNull will replace a float value to null if it is +/-Inf.
|
||
//
|
||
// OptFloatInfToNull 表示当遇到 +/-Inf 时,将值替换成 null
|
||
func OptFloatInfToNull() Option {
|
||
return optFloatInfNull{}
|
||
}
|
||
|
||
type optFloatInfNull struct{}
|
||
|
||
func (optFloatInfNull) mergeTo(opt *Opt) {
|
||
opt.FloatInfHandleType = FloatInfNull
|
||
}
|
||
|
||
// ==== FloatInfConvertToString ====
|
||
|
||
// OptFloatInfToStringInf will replace a +Inf value to string "+Inf", while -Inf to "-Inf"
|
||
//
|
||
// OptFloatInfToStringInf 表示遇到 +/-Inf 时,相应地将其替换成字符串 "+Inf" 和 "-Inf"
|
||
func OptFloatInfToStringInf() Option {
|
||
return &optFloatInfConvertToString{}
|
||
}
|
||
|
||
// OptFloatInfToString tells what string to replace when marshaling +Inf and -Inf numbers.
|
||
//
|
||
// OptFloatInfToString 表示遇到 +/-Inf 时,将其替换成什么字符串。
|
||
func OptFloatInfToString(positiveInf, negativeInf string) Option {
|
||
return &optFloatInfConvertToString{
|
||
positive: positiveInf,
|
||
negative: negativeInf,
|
||
}
|
||
}
|
||
|
||
type optFloatInfConvertToString struct {
|
||
positive string
|
||
negative string
|
||
}
|
||
|
||
func (o *optFloatInfConvertToString) mergeTo(opt *Opt) {
|
||
opt.FloatInfHandleType = FloatInfConvertToString
|
||
opt.FloatInfPositiveToString = o.positive
|
||
opt.FloatInfNegativeToString = o.negative
|
||
}
|
||
|
||
// ==== escapeHTML ====
|
||
|
||
// OptEscapeHTML specifies whether problematic HTML characters should be escaped
|
||
// inside JSON quoted strings. The default behavior is to escape &, <, and > to
|
||
// \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when
|
||
// embedding JSON in HTML. If not specified, HTML symbols above will be escaped by
|
||
// default.
|
||
//
|
||
// OptEscapeHTML 指定部分 HTML 符号是否会被转义。相关的 HTML 符号为 &, <, > 三个。如无指定,
|
||
// 则默认会被转义
|
||
func OptEscapeHTML(on bool) Option {
|
||
return optEscapeHTML(on)
|
||
}
|
||
|
||
type optEscapeHTML bool
|
||
|
||
func (o optEscapeHTML) mergeTo(opt *Opt) {
|
||
if o {
|
||
opt.escProperties = opt.escProperties.clear(escapeWithoutHTML)
|
||
} else {
|
||
opt.escProperties = opt.escProperties.set(escapeWithoutHTML)
|
||
}
|
||
}
|
||
|
||
// ==== do or do not not use ASCII escaping ====
|
||
|
||
// OptUTF8 specifies that all unicodes greater than 0x7F, will NOT be escaped by
|
||
// \uXXXX format but UTF-8.
|
||
//
|
||
// OptUTF8 指定使用 UTF-8 编码。也就是说针对大于 0x7F 的 unicode 字符,将不会使用默认的 \uXXXX
|
||
// 格式进行编码,而是直接使用 UTF-8。
|
||
func OptUTF8() Option {
|
||
return optUTF8(true)
|
||
}
|
||
|
||
type optUTF8 bool
|
||
|
||
func (o optUTF8) mergeTo(opt *Opt) {
|
||
opt.escProperties = opt.escProperties.set(escapeUTF8)
|
||
}
|
||
|
||
// ==== ignore slash ====
|
||
|
||
// OptEscapeSlash specifies whether we should escape slash (/) symbol. In JSON standard,
|
||
// this character should be escaped as '\/'. But non-escaping will not affect anything.
|
||
// If not specfied, slash will be escaped by default.
|
||
//
|
||
// OptEscapeSlash 指定是否需要转移斜杠 (/) 符号。在 JSON 标准中这个符号是需要被转移为 '\/' 的,
|
||
//
|
||
// 但是不转义这个符号也不会带来什么问题。如无明确指定,如无指定,默认情况下,斜杠是会被转义的。
|
||
func OptEscapeSlash(on bool) Option {
|
||
return optEscSlash(on)
|
||
}
|
||
|
||
type optEscSlash bool
|
||
|
||
func (o optEscSlash) mergeTo(opt *Opt) {
|
||
if o {
|
||
opt.escProperties = opt.escProperties.clear(escapeIgnoreSlash)
|
||
} else {
|
||
opt.escProperties = opt.escProperties.set(escapeIgnoreSlash)
|
||
}
|
||
}
|
||
|
||
// escapingProperties is a bit mask, showing the option for escaping
|
||
// characters.
|
||
//
|
||
// escapingProperties 是一个位掩码,表明转义特殊字符的方法
|
||
type escapingProperties uint8
|
||
|
||
const (
|
||
escapeUTF8 = 0
|
||
escapeWithoutHTML = 1
|
||
escapeIgnoreSlash = 2
|
||
)
|
||
|
||
func (esc escapingProperties) set(mask escapingProperties) escapingProperties {
|
||
return esc | (1 << mask)
|
||
}
|
||
|
||
func (esc escapingProperties) clear(mask escapingProperties) escapingProperties {
|
||
return esc & ^(1 << mask)
|
||
}
|
||
|
||
func (esc escapingProperties) has(mask escapingProperties) bool {
|
||
return esc == esc.set(mask)
|
||
}
|
||
|
||
// parseEscapingFuncs parse escaping functions by escapingProperties.
|
||
func (o *Opt) parseEscapingFuncs() {
|
||
// init bytes lower than 0x80
|
||
for i := range o.asciiCharEscapingFunc {
|
||
o.asciiCharEscapingFunc[i] = escapeNothing
|
||
}
|
||
|
||
iterate := func(from, to int, fu func(b byte, buf buffer.Buffer)) {
|
||
for i := from; i <= to; i++ {
|
||
o.asciiCharEscapingFunc[i] = fu
|
||
}
|
||
}
|
||
|
||
// ASCII control bytes should always escaped
|
||
iterate(0x00, 0x07, escAsciiControlChar)
|
||
// 0x08 is \b, encoding/json marshal as \u0008, but according to JSON standard, it should be "\b"
|
||
iterate(0x0E, 0x1F, escAsciiControlChar)
|
||
o.asciiCharEscapingFunc[0x7F] = escAsciiControlChar // encoding/json does not escape DEL
|
||
|
||
// ASCII characters always to be escaped
|
||
o.asciiCharEscapingFunc['"'] = escDoubleQuote
|
||
o.asciiCharEscapingFunc['/'] = escSlash
|
||
o.asciiCharEscapingFunc['\\'] = escBackslash
|
||
o.asciiCharEscapingFunc['\b'] = escBackspace
|
||
o.asciiCharEscapingFunc['\f'] = escVertTab
|
||
o.asciiCharEscapingFunc['\t'] = escTab
|
||
o.asciiCharEscapingFunc['\n'] = escNewLine
|
||
o.asciiCharEscapingFunc['\r'] = escReturn
|
||
o.asciiCharEscapingFunc['<'] = escLeftAngle
|
||
o.asciiCharEscapingFunc['>'] = escRightAngle
|
||
o.asciiCharEscapingFunc['&'] = escAnd
|
||
// o.asciiCharEscapingFunc['%'] = escPercent
|
||
|
||
// unicodes >= 0x80
|
||
if o.escProperties.has(escapeUTF8) {
|
||
o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF8
|
||
} else {
|
||
o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF16
|
||
}
|
||
|
||
// ignore slash?
|
||
if o.escProperties.has(escapeIgnoreSlash) {
|
||
o.asciiCharEscapingFunc['/'] = escapeNothing
|
||
}
|
||
|
||
// without HTML?
|
||
if o.escProperties.has(escapeWithoutHTML) {
|
||
o.asciiCharEscapingFunc['<'] = escapeNothing
|
||
o.asciiCharEscapingFunc['>'] = escapeNothing
|
||
o.asciiCharEscapingFunc['&'] = escapeNothing
|
||
}
|
||
}
|
||
|
||
// ==== indent ====
|
||
|
||
// OptIndent appliesiIndent to format the output.
|
||
//
|
||
// OptIndent 指定序列化时的缩进。
|
||
func OptIndent(prefix, indent string) Option {
|
||
return optionIndent{prefix, indent}
|
||
}
|
||
|
||
type optionIndent [2]string
|
||
|
||
func (o optionIndent) mergeTo(opt *Opt) {
|
||
opt.indent.enabled = true
|
||
opt.indent.prefix = o[0]
|
||
opt.indent.indent = o[1]
|
||
}
|