-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Closed
Description
Component(s)
pdata
Describe the issue you're reporting
Background
We aim to store the complex types (map, slice) of value within attributes as JSON safely. Currently, serializing them to JSON strings using value.AsString() leads to the risk of losing type information during deserialization. Specifically:
- All numerical values become JSON numbers, making it impossible to distinguish whether a value was originally an
int64or afloat64. - Parsing nested
mapandslicestructures is particularly problematic due to their dynamic and unpredictable nesting levels.
Solution
This issue can be resolved with a minor modification. Instead of directly serializing and deserializing the high-level Value type, we will operate on the underlying otlpcommon.AnyValue type it holds. AnyValue is a Go struct generated from Protobuf definitions, which allows for a more precise representation of different data types.
Here is the code implementing this functionality:
import oteljson "go.opentelemetry.io/collector/pdata/internal/json"
import "go.opentelemetry.io/collector/pdata/internal"
import "go.opentelemetry.io/proto/otlp/common/v1"
// UnmarshalValue deserializes a JSON byte stream into a Value type.
// It uses oteljson.ReadValue to read the JSON data into an AnyValue,
// and then creates a new Value instance using the AnyValue.
func UnmarshalValue(buf []byte) Value {
iter := jsoniter.ConfigFastest.BorrowIterator(buf)
defer jsoniter.ConfigFastest.ReturnIterator(iter)
var anyValue v1.AnyValue // Using the correct Protobuf-generated AnyValue type
state := internal.StateMutable
oteljson.ReadValue(iter, &anyValue)
return newValue(&anyValue, &state)
}
// MarshalValue serializes a Value type into a JSON byte stream.
// It retrieves the underlying AnyValue using value.getOrig()
// and then uses oteljson.Marshal to serialize the AnyValue into JSON.
func MarshalValue(value Value) ([]byte, error) {
var buf bytes.Buffer
if err := oteljson.Marshal(&buf, value.getOrig()); err != nil {
return nil, err
}
return buf.Bytes(), nil
}Metadata
Metadata
Assignees
Labels
No labels