encodeJsonObject encodes the specified |jsonValue| into MySQL's internal JSON encoding and returns the type ID indicating what type of value this is, the encoded value, and any error encountered.
(jsonValue any)
| 231 | |
| 232 | // encodeJsonObject encodes the specified |jsonValue| into MySQL's internal JSON encoding and returns |
| 233 | // the type ID indicating what type of value this is, the encoded value, and any error encountered. |
| 234 | func encodeJsonValue(jsonValue any) (typeId byte, buffer []byte, err error) { |
| 235 | if jsonValue == nil { |
| 236 | buffer = append(buffer, jsonLiteralValueNull) |
| 237 | return jsonTypeLiteral, buffer, nil |
| 238 | } |
| 239 | |
| 240 | switch v := jsonValue.(type) { |
| 241 | case bool: |
| 242 | if v { |
| 243 | buffer = append(buffer, jsonLiteralValueTrue) |
| 244 | } else { |
| 245 | buffer = append(buffer, jsonLiteralValueFalse) |
| 246 | } |
| 247 | return jsonTypeLiteral, buffer, nil |
| 248 | |
| 249 | case string: |
| 250 | // String lengths use a special encoding that can span multiple bytes |
| 251 | buffer, err = appendStringLength(buffer, len(v)) |
| 252 | if err != nil { |
| 253 | return 0, nil, err |
| 254 | } |
| 255 | |
| 256 | buffer = append(buffer, []byte(v)...) |
| 257 | return jsonTypeString, buffer, nil |
| 258 | |
| 259 | case float64: |
| 260 | // NOTE: all our numbers end up being represented as float64s currently when we parse stored JSON |
| 261 | bits := math.Float64bits(v) |
| 262 | buffer = append(buffer, make([]byte, 8)...) |
| 263 | binary.LittleEndian.PutUint64(buffer, bits) |
| 264 | return jsonTypeDouble, buffer, nil |
| 265 | |
| 266 | case []any: |
| 267 | // MySQL attempts to use the small encoding first, and if offset sizes overflow, then it switches to the |
| 268 | // large encoding. This is a little messy/inefficient to try the small encoding first, but because of the |
| 269 | // way the binary format is designed, we can't know if/when we'll need the large format without serializing |
| 270 | // the data first. |
| 271 | id, encodedArray, err := encodeJsonArray(v, false) |
| 272 | if err == nil { |
| 273 | return id, encodedArray, nil |
| 274 | } |
| 275 | return encodeJsonArray(v, true) |
| 276 | |
| 277 | case map[string]any: |
| 278 | // See the comment above about MySQL's JSON serialization format, and why we try the small encoding first, |
| 279 | // before we know if we need the large encoding or not. |
| 280 | id, encodedObject, err := encodeJsonObject(v, false) |
| 281 | if err == nil { |
| 282 | return id, encodedObject, nil |
| 283 | } |
| 284 | return encodeJsonObject(v, true) |
| 285 | |
| 286 | default: |
| 287 | return 0x00, nil, fmt.Errorf("unexpected type in JSON document: %T", v) |
| 288 | } |
| 289 | } |
| 290 |
no test coverage detected