github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/marshal.go (about) 1 // MIT License 2 // 3 // Copyright (c) 2021 Xiantu Li 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 package json 24 25 import ( 26 "encoding" 27 stdjson "encoding/json" 28 "fmt" 29 "reflect" 30 "strconv" 31 "strings" 32 33 lxterrs "github.com/lxt1045/errors" 34 ) 35 36 /* 37 fget 函数 list ,打入slice中,然后依次遍历slice,避免了遍历struct 的多个for循环!! greate! 38 golang不支持尾递归,可能嵌套调用性能没有fget list 方式好 39 */ 40 41 // bsGrow 在 slice marshal 的时候可以根据第一个的序列化结果计算出还需要的长度,如果 bs 不足则提前分配是比较好的选择 42 func bsGrow(in []byte, lNeed int) (out []byte) { 43 lNew := bsPoolN 44 if lNew < lNeed+len(in) { 45 lNew += lNeed + len(in) 46 } 47 bsNew := make([]byte, 0, lNew) 48 out = append(bsNew, in...) 49 return 50 } 51 52 // 排列一个 fM list,优化掉多个 for 循环 53 func marshalStruct(store Store, in []byte) (out []byte) { 54 out = append(in, '{') 55 for _, tag := range store.tag.ChildList { 56 out = append(out, tag.TagName...) 57 out = append(out, ':') 58 59 pObj := pointerOffset(store.obj, tag.Offset) 60 out = tag.fM(Store{obj: pObj, tag: tag}, out) 61 62 out = append(out, ',') 63 } 64 out[len(out)-1] = '}' 65 return 66 } 67 68 // marshalT 序列化明确的类型 69 func marshalT(in []byte, store Store) (out []byte) { 70 out = in 71 panic(lxterrs.Errorf("error tag, fM is nil:%+v", store.tag)) 72 73 return 74 } 75 76 // TODO: 根据一个 marshal 的 len 乘以 len(m) ,达到还需要的空间,如果不足则 New? 77 func marshalSlice(bs []byte, store Store, l int) (out []byte) { 78 out = append(bs, '[') 79 if l <= 0 { 80 out = append(out, ']') 81 return 82 } 83 son := store.tag 84 size := son.TypeSize 85 86 lBefore := len(out) 87 out = son.fM(Store{obj: store.obj, tag: son}, out) 88 lObj := len(out) - lBefore + 1 + 16 // 16 随意取的值 89 // 解析还需要的空间 90 if lNeed := lObj * (l - 1); cap(out)-len(out) < lNeed { 91 out = bsGrow(out, lNeed) 92 } 93 94 for i := 1; i < l; i++ { 95 out = append(out, ',') 96 pSon := pointerOffset(store.obj, uintptr(i*size)) 97 out = son.fM(Store{obj: pSon, tag: son}, out) 98 } 99 out = append(out, ']') 100 return 101 } 102 func marshalInterface(bs []byte, iface interface{}) (out []byte) { 103 if iface == nil { 104 out = append(bs, "null"...) 105 return 106 } 107 out = bs 108 switch v := iface.(type) { 109 case int8: 110 out = strconv.AppendInt(out, int64(v), 10) 111 case int16: 112 out = strconv.AppendInt(out, int64(v), 10) 113 case int32: 114 out = strconv.AppendInt(out, int64(v), 10) 115 case int64: 116 out = strconv.AppendInt(out, int64(v), 10) 117 case int: 118 out = strconv.AppendInt(out, int64(v), 10) 119 case uint8: 120 out = strconv.AppendUint(out, uint64(v), 10) 121 case uint16: 122 out = strconv.AppendUint(out, uint64(v), 10) 123 case uint32: 124 out = strconv.AppendUint(out, uint64(v), 10) 125 case uint64: 126 out = strconv.AppendUint(out, uint64(v), 10) 127 case uint: 128 out = strconv.AppendUint(out, uint64(v), 10) 129 case float32: 130 out = strconv.AppendFloat(out, float64(v), 'f', -1, 32) 131 case float64: 132 out = strconv.AppendFloat(out, v, 'f', -1, 64) 133 case string: 134 out = append(out, '"') 135 out = append(out, v...) 136 out = append(out, '"') 137 case stdjson.Number: 138 // TODO: 检查 numStr 的有效性? 139 out = append(out, v.String()...) 140 case map[string]interface{}: 141 out = marshalMapInterface(out, v) 142 case []interface{}: 143 out = append(out, '[') 144 for i, iface := range v { 145 if i != 0 { 146 out = append(out, ',') 147 } 148 marshalInterface(out, iface) 149 } 150 out = append(out, ']') 151 case []byte: 152 panic("TODO: []byte...") 153 default: 154 value := reflect.ValueOf(iface) 155 out = marshalValue(out, value) 156 } 157 return 158 } 159 160 // TODO: 根据一个 marshal 的 len 乘以 len(m) ,达到还需要的空间,如果不足则 New? 161 func marshalMapInterface(bs []byte, m map[string]interface{}) (out []byte) { 162 out = bs 163 out = append(out, '{') 164 if len(m) == 0 { 165 out = append(out, '}') 166 return 167 } 168 169 first := true 170 for k, v := range m { 171 if first { 172 first = false 173 lBefore := len(out) 174 out = append(out, '"') 175 out = append(out, k...) 176 out = append(out, `":`...) 177 out = marshalInterface(out, v) 178 lObj := len(out) - lBefore + 1 + 16 // 16 随意取的值 179 if lNeed := lObj * (len(m) - 1); cap(out)-len(out) < lNeed { 180 out = bsGrow(out, lNeed) 181 } 182 continue 183 } 184 out = append(out, `,"`...) 185 out = append(out, k...) 186 out = append(out, `":`...) 187 out = marshalInterface(out, v) 188 } 189 out = append(out, '}') 190 return 191 } 192 193 func marshalValue(bs []byte, value reflect.Value) (out []byte) { 194 out = bs 195 196 // 针对指针 197 for value.Kind() == reflect.Ptr { 198 if value.IsNil() { 199 out = append(out, "null"...) 200 return 201 } 202 value = value.Elem() 203 } 204 205 switch value.Kind() { 206 case reflect.Interface: 207 if value.IsNil() { 208 out = append(out, "null"...) 209 return 210 } 211 // UnpackEface(&value) 212 // 从 iterface{} 里取出原始类型 213 value := reflect.ValueOf(value.Interface()) 214 out = marshalValue(bs, value) 215 return 216 case reflect.Map: 217 if value.IsNil() { 218 out = append(out, "null"...) 219 return 220 } 221 iter := value.MapRange() 222 if iter == nil { 223 return 224 } 225 out = append(out, '{') 226 l := len(out) 227 for iter.Next() { 228 out = marshalKey(out, iter.Key()) 229 out = append(out, ':') 230 out = marshalValue(out, iter.Value()) 231 out = append(out, ',') 232 } 233 if l < len(out) { 234 out = out[:len(out)-1] 235 } 236 out = append(out, '}') 237 return 238 case reflect.Slice: 239 if value.IsNil() { 240 out = append(out, "[]"...) 241 return 242 } 243 out = append(out, '[') 244 lBefore := len(out) 245 v := value.Index(0) 246 out = marshalValue(out, v) 247 lObj := len(out) - lBefore + 1 + 16 // 16 随意取的值 248 // 解析还需要的空间 249 if lNeed := lObj * (value.Len() - 1); cap(out)-len(out) < lNeed { 250 out = bsGrow(out, lNeed) 251 } 252 for i := 1; i < value.Len(); i++ { 253 out = append(out, ',') 254 v := value.Index(i) 255 out = marshalValue(out, v) 256 } 257 out = append(out, ']') 258 return 259 case reflect.Struct: 260 prv := reflectValueToValue(&value) 261 goType := prv.typ 262 263 tag, err := LoadTagNode(value, goType.Hash) 264 if err != nil { 265 return 266 } 267 268 store := Store{ 269 tag: tag, 270 obj: prv.ptr, // eface.Value, 271 } 272 out = marshalStruct(store, out) 273 return 274 case reflect.Bool: 275 if value.Bool() { 276 out = append(out, "true"...) 277 } else { 278 out = append(out, "false"...) 279 } 280 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 281 out = strconv.AppendUint(out, value.Uint(), 10) 282 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 283 out = strconv.AppendInt(out, value.Int(), 10) 284 case reflect.Float64: 285 out = strconv.AppendFloat(out, value.Float(), 'f', -1, 64) 286 case reflect.Float32: 287 out = strconv.AppendFloat(out, value.Float(), 'f', -1, 32) 288 case reflect.String: 289 if value.Type() == jsonNumberType { 290 numStr := value.String() 291 // TODO: 检查 numStr 的有效性? 292 out = append(out, numStr...) 293 return 294 } 295 out = append(out, '"') 296 // out = append(out, value.String()...) // TODO 需要转义: \ --> \\ 297 str := value.String() 298 nQuote := strings.Count(str, "\"") // 只处理 " , \ 可以不处理 299 if nQuote == 0 { 300 out = append(out, str...) // TODO 需要转义: \ --> \\ 301 } else { 302 for { 303 i := strings.IndexByte(str, '"') 304 if i == -1 { 305 out = append(out, str...) 306 break 307 } 308 out = append(out, str[:i]...) 309 out = append(out, '\\', '"') 310 str = str[i+1:] 311 } 312 } 313 out = append(out, '"') 314 return 315 default: 316 // out = append(out, "null"...) 317 panic(fmt.Sprintf("TODO: kind:%d...", value.Kind())) 318 } 319 320 return 321 } 322 323 var jsonNumberType = reflect.TypeOf(stdjson.Number("")) 324 325 func marshalKey(in []byte, k reflect.Value) (out []byte) { 326 out = in 327 if k.Kind() == reflect.String { 328 // key = k.String() 329 out = append(out, '"') 330 // out = append(out, k.String()...) // TODO 需要转义: \ --> \\ 331 str := k.String() 332 nQuote := strings.Count(str, "\"") // 只处理 " , \ 可以不处理 333 if nQuote == 0 { 334 out = append(out, str...) // TODO 需要转义: \ --> \\ 335 } else { 336 for { 337 i := strings.IndexByte(str, '"') 338 if i == -1 { 339 out = append(out, str...) 340 break 341 } 342 out = append(out, str[:i]...) 343 out = append(out, '\\', '"') 344 str = str[i+1:] 345 } 346 } 347 out = append(out, '"') 348 return 349 } 350 if tm, ok := k.Interface().(encoding.TextMarshaler); ok { 351 if k.Kind() == reflect.Pointer && k.IsNil() { 352 return 353 } 354 bs, err := tm.MarshalText() 355 if err != nil { 356 err = lxterrs.Wrap(err, "MarshalText() got error") 357 panic(err) 358 } 359 // key = string(bs) 360 out = append(out, '"') 361 out = append(out, bs...) 362 out = append(out, '"') 363 return 364 } 365 switch k.Kind() { 366 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 367 // key = strconv.FormatInt(k.Int(), 10) 368 out = append(out, '"') 369 out = strconv.AppendInt(out, k.Int(), 10) 370 out = append(out, '"') 371 return 372 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 373 // key = strconv.FormatUint(k.Uint(), 10) 374 out = append(out, '"') 375 out = strconv.AppendUint(out, k.Uint(), 10) 376 out = append(out, '"') 377 return 378 } 379 err := lxterrs.New("unexpected map key type") 380 panic(err) 381 }