InjectJSONProperties takes the given JSON byte slice, and for each KV pair, marshals the value and inserts into the returned byte slice under the given key, without modifying the given byte slice. This has the potential to create duplicate keys, which whilst adhering to the spec, are ambiguous with
(b []byte, kvPairs ...KVPair)
| 1310 | // This has the potential to create duplicate keys, which whilst adhering to the spec, are ambiguous with how they get read... |
| 1311 | // usually "last key wins" - although there is no standardized way of handling JSON with non-unique keys. |
| 1312 | func InjectJSONProperties(b []byte, kvPairs ...KVPair) (new []byte, err error) { |
| 1313 | if len(kvPairs) == 0 { |
| 1314 | // noop |
| 1315 | return b, nil |
| 1316 | } |
| 1317 | |
| 1318 | b = bytes.TrimSpace(b) |
| 1319 | |
| 1320 | bIsJSONObject, bIsEmpty := isJSONObject(b) |
| 1321 | if !bIsJSONObject { |
| 1322 | return nil, errors.New("b is not a JSON object") |
| 1323 | } |
| 1324 | |
| 1325 | kvPairsBytes := make([]KVPairBytes, len(kvPairs)) |
| 1326 | for i, kv := range kvPairs { |
| 1327 | var valBytes []byte |
| 1328 | var err error |
| 1329 | |
| 1330 | switch v := kv.Val.(type) { |
| 1331 | case int: |
| 1332 | valBytes = []byte(strconv.FormatInt(int64(v), 10)) |
| 1333 | case int8: |
| 1334 | valBytes = []byte(strconv.FormatInt(int64(v), 10)) |
| 1335 | case int16: |
| 1336 | valBytes = []byte(strconv.FormatInt(int64(v), 10)) |
| 1337 | case int32: |
| 1338 | valBytes = []byte(strconv.FormatInt(int64(v), 10)) |
| 1339 | case int64: |
| 1340 | valBytes = []byte(strconv.FormatInt(v, 10)) |
| 1341 | case uint: |
| 1342 | valBytes = []byte(strconv.FormatUint(uint64(v), 10)) |
| 1343 | case uint8: |
| 1344 | valBytes = []byte(strconv.FormatUint(uint64(v), 10)) |
| 1345 | case uint16: |
| 1346 | valBytes = []byte(strconv.FormatUint(uint64(v), 10)) |
| 1347 | case uint32: |
| 1348 | valBytes = []byte(strconv.FormatUint(uint64(v), 10)) |
| 1349 | case uint64: |
| 1350 | valBytes = []byte(strconv.FormatUint(v, 10)) |
| 1351 | case bool: |
| 1352 | valBytes = []byte(strconv.FormatBool(v)) |
| 1353 | // case string: |
| 1354 | // it's not safe to use strings without marshalling |
| 1355 | // fall through to default below |
| 1356 | default: |
| 1357 | valBytes, err = JSONMarshal(kv.Val) |
| 1358 | } |
| 1359 | if err != nil { |
| 1360 | return nil, err |
| 1361 | } |
| 1362 | kvPairsBytes[i] = KVPairBytes{Key: kv.Key, Val: valBytes} |
| 1363 | } |
| 1364 | |
| 1365 | return injectJSONPropertyFromBytes(b, bIsEmpty, kvPairsBytes), nil |
| 1366 | } |
| 1367 | |
| 1368 | // KVPairBytes represents a single KV pair to be used in InjectJSONPropertiesFromBytes |
| 1369 | type KVPairBytes struct { |