Skip to content

Commit e1a3494

Browse files
Vaalla42TommyCpplalitb
authored
When deserializing JSON, accept both int and string in 'intValue' (#1906)
Co-authored-by: Zhongyang Wu <zhongyang.wu@outlook.com> Co-authored-by: Lalit Kumar Bhasin <labhas@microsoft.com>
1 parent 0e8f259 commit e1a3494

File tree

3 files changed

+118
-63
lines changed

3 files changed

+118
-63
lines changed

opentelemetry-otlp/tests/integration_test/expected/traces.json

+6
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@
8888
"value": {
8989
"intValue": "100"
9090
}
91+
},
92+
{
93+
"key": "number/int",
94+
"value": {
95+
"intValue": 100
96+
}
9197
}
9298
]
9399
}

opentelemetry-proto/src/proto.rs

+82-63
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ pub(crate) mod serializers {
5757
Ok(s) => s,
5858
Err(e) => return Err(e), // Handle the error or return it
5959
};
60-
60+
6161
// Attempt to serialize the intValue field
6262
if let Err(e) = state.serialize_field("intValue", &i.to_string()) {
6363
return Err(e); // Handle the error or return it
6464
}
65-
65+
6666
// Finalize the struct serialization
6767
state.end()
68-
},
68+
}
6969
Some(value) => value.serialize(serializer),
7070
None => serializer.serialize_none(),
7171
},
@@ -74,76 +74,95 @@ pub(crate) mod serializers {
7474
}
7575

7676
pub fn deserialize_from_value<'de, D>(deserializer: D) -> Result<Option<AnyValue>, D::Error>
77-
where
78-
D: Deserializer<'de>,
79-
{
80-
struct ValueVisitor;
77+
where
78+
D: Deserializer<'de>,
79+
{
80+
struct ValueVisitor;
8181

82-
impl<'de> de::Visitor<'de> for ValueVisitor {
83-
type Value = AnyValue;
82+
#[derive(Deserialize)]
83+
#[serde(untagged)]
84+
enum StringOrInt {
85+
Int(i64),
86+
String(String),
87+
}
8488

85-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
86-
formatter.write_str("a JSON object for AnyValue")
89+
impl StringOrInt {
90+
fn get_int<'de, V>(&self) -> Result<i64, V::Error>
91+
where
92+
V: de::MapAccess<'de>,
93+
{
94+
match self {
95+
Self::Int(val) => Ok(*val),
96+
Self::String(val) => Ok(val.parse::<i64>().map_err(de::Error::custom)?),
97+
}
98+
}
8799
}
88100

89-
fn visit_map<V>(self, mut map: V) -> Result<AnyValue, V::Error>
90-
where
91-
V: de::MapAccess<'de>,
92-
{
93-
let mut value: Option<any_value::Value> = None;
94-
95-
while let Some(key) = map.next_key::<String>()? {
96-
let key_str = key.as_str();
97-
match key_str {
98-
"stringValue" => {
99-
let s = map.next_value()?;
100-
value = Some(any_value::Value::StringValue(s));
101-
},
102-
"boolValue" => {
103-
let b = map.next_value()?;
104-
value = Some(any_value::Value::BoolValue(b));
105-
},
106-
"intValue" => {
107-
let value_str = map.next_value::<String>()?;
108-
let int_value = value_str.parse::<i64>()
109-
.map_err(de::Error::custom)?;
110-
value = Some(any_value::Value::IntValue(int_value));
111-
},
112-
"doubleValue" => {
113-
let d = map.next_value()?;
114-
value = Some(any_value::Value::DoubleValue(d));
115-
},
116-
"arrayValue" => {
117-
let a = map.next_value()?;
118-
value = Some(any_value::Value::ArrayValue(a));
119-
},
120-
"kvlistValue" => {
121-
let kv = map.next_value()?;
122-
value = Some(any_value::Value::KvlistValue(kv));
123-
},
124-
"bytesValue" => {
125-
let bytes = map.next_value()?;
126-
value = Some(any_value::Value::BytesValue(bytes));
127-
},
128-
_ => {
129-
//skip unknown keys, and handle error later.
130-
continue
101+
impl<'de> de::Visitor<'de> for ValueVisitor {
102+
type Value = AnyValue;
103+
104+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
105+
formatter.write_str("a JSON object for AnyValue")
106+
}
107+
108+
fn visit_map<V>(self, mut map: V) -> Result<AnyValue, V::Error>
109+
where
110+
V: de::MapAccess<'de>,
111+
{
112+
let mut value: Option<any_value::Value> = None;
113+
114+
while let Some(key) = map.next_key::<String>()? {
115+
let key_str = key.as_str();
116+
match key_str {
117+
"stringValue" => {
118+
let s = map.next_value()?;
119+
value = Some(any_value::Value::StringValue(s));
120+
}
121+
"boolValue" => {
122+
let b = map.next_value()?;
123+
value = Some(any_value::Value::BoolValue(b));
124+
}
125+
"intValue" => {
126+
let int_value = map.next_value::<StringOrInt>()?.get_int::<V>()?;
127+
value = Some(any_value::Value::IntValue(int_value));
128+
}
129+
"doubleValue" => {
130+
let d = map.next_value()?;
131+
value = Some(any_value::Value::DoubleValue(d));
132+
}
133+
"arrayValue" => {
134+
let a = map.next_value()?;
135+
value = Some(any_value::Value::ArrayValue(a));
136+
}
137+
"kvlistValue" => {
138+
let kv = map.next_value()?;
139+
value = Some(any_value::Value::KvlistValue(kv));
140+
}
141+
"bytesValue" => {
142+
let bytes = map.next_value()?;
143+
value = Some(any_value::Value::BytesValue(bytes));
144+
}
145+
_ => {
146+
//skip unknown keys, and handle error later.
147+
continue;
148+
}
131149
}
132150
}
133-
}
134151

135-
if let Some(v) = value {
136-
Ok(AnyValue { value: Some(v) })
137-
} else {
138-
Err(de::Error::custom("Invalid data for AnyValue, no known keys found"))
152+
if let Some(v) = value {
153+
Ok(AnyValue { value: Some(v) })
154+
} else {
155+
Err(de::Error::custom(
156+
"Invalid data for AnyValue, no known keys found",
157+
))
158+
}
139159
}
140160
}
161+
162+
let value = deserializer.deserialize_map(ValueVisitor)?;
163+
Ok(Some(value))
141164
}
142165

143-
let value = deserializer.deserialize_map(ValueVisitor)?;
144-
Ok(Some(value))
145-
}
146-
147166
pub fn serialize_u64_to_string<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
148167
where
149168
S: Serializer,
@@ -167,7 +186,7 @@ where
167186
let s = value.to_string();
168187
serializer.serialize_str(&s)
169188
}
170-
189+
171190
pub fn deserialize_string_to_i64<'de, D>(deserializer: D) -> Result<i64, D::Error>
172191
where
173192
D: Deserializer<'de>,

opentelemetry-proto/tests/json_deserialize.rs

+30
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,36 @@ mod json_deserialize {
146146
keyvalue.value.unwrap().value.unwrap(),
147147
Value::StringValue("my.service".to_string())
148148
);
149+
150+
let keyvalue: KeyValue = serde_json::from_str(
151+
r#"
152+
{
153+
"key": "service.name",
154+
"value": {
155+
"intValue": "303"
156+
}
157+
}
158+
"#,
159+
)
160+
.unwrap();
161+
162+
assert_eq!(keyvalue.key, "service.name".to_string());
163+
assert_eq!(keyvalue.value.unwrap().value.unwrap(), Value::IntValue(303));
164+
165+
let keyvalue: KeyValue = serde_json::from_str(
166+
r#"
167+
{
168+
"key": "service.name",
169+
"value": {
170+
"intValue": 303
171+
}
172+
}
173+
"#,
174+
)
175+
.unwrap();
176+
177+
assert_eq!(keyvalue.key, "service.name".to_string());
178+
assert_eq!(keyvalue.value.unwrap().value.unwrap(), Value::IntValue(303));
149179
}
150180

151181
#[test]

0 commit comments

Comments
 (0)