Description
When invoking a contract that returns a Map<Symbol, V> or Map<String, V>, the keys in the JSON output are incorrectly double-encoded, making them unreadable.
Steps to Reproduce
Given a contract function:
pub fn echo_map(_env: Env, value: Map<Symbol, u32>) -> Map<Symbol, u32> {
value
}
Invoke it:
stellar contract invoke --id mycontract -- echo_map --value '{"bar":1,"foo":2}'
Actual Output
{"\"bar\"":1,"\"foo\"":2}
The keys contain literal backslash-quote sequences, making the output invalid as idiomatic JSON (the key values have embedded double-quote characters).
Expected Output
Root Cause
In Spec::sc_map_to_json (cmd/crates/soroban-spec-tools/src/lib.rs:616):
let key_s = self.xdr_to_json(key, &type_.key_type)?.to_string();
xdr_to_json for a ScVal::Symbol("bar") correctly returns Value::String("bar"). However, calling .to_string() on a serde_json::Value invokes serde_json::to_string(), which JSON-serializes the value — wrapping the string in quotes and escaping them. The resulting string is "\"bar\"" (seven characters, including the surrounding quotes), which is then inserted as the JSON object key.
The fix should extract the raw inner string from Value::String instead of JSON-serializing it, for example by matching on Value::String(s) => s or by using the free-function to_string from soroban-spec-tools (which already handles ScVal::Symbol correctly without the extra encoding).
Affected Types
Any Map<K, V> where K is Symbol, String, or any other type whose xdr_to_json representation is Value::String.
Description
When invoking a contract that returns a
Map<Symbol, V>orMap<String, V>, the keys in the JSON output are incorrectly double-encoded, making them unreadable.Steps to Reproduce
Given a contract function:
Invoke it:
stellar contract invoke --id mycontract -- echo_map --value '{"bar":1,"foo":2}'Actual Output
The keys contain literal backslash-quote sequences, making the output invalid as idiomatic JSON (the key values have embedded double-quote characters).
Expected Output
Root Cause
In
Spec::sc_map_to_json(cmd/crates/soroban-spec-tools/src/lib.rs:616):xdr_to_jsonfor aScVal::Symbol("bar")correctly returnsValue::String("bar"). However, calling.to_string()on aserde_json::Valueinvokesserde_json::to_string(), which JSON-serializes the value — wrapping the string in quotes and escaping them. The resulting string is"\"bar\""(seven characters, including the surrounding quotes), which is then inserted as the JSON object key.The fix should extract the raw inner string from
Value::Stringinstead of JSON-serializing it, for example by matching onValue::String(s) => sor by using the free-functionto_stringfrom soroban-spec-tools (which already handlesScVal::Symbolcorrectly without the extra encoding).Affected Types
Any
Map<K, V>whereKisSymbol,String, or any other type whosexdr_to_jsonrepresentation isValue::String.