JsonString is a type in the schema for arbitrary JSON values. In SCALE it is encoded as a string (hence the name), while in JSON it is inlined as any JSON value.
There are a few issues:
Ambiguity of Option<JsonString> in JSON: it is impossible to distinguish between None and Some("null"), since both serialize as null in actual JSON.
Schema's purpose is solely to describe SCALE encoding and it doesn't tell anything about JsonString representation in JSON. In JSON it is not a string, which caused confusion for SDK developers.
This PR fixes #4900 by disallowing Option<JsonString> and essentially forcing SDKs to handle JSON values as a special case and account for its differences in SCALE vs JSON.
Solution
by these changes:
Rename JsonString to JsonValue and make stronger emphasis on using the native Rust JSON type, i.e. serde_json::Value. Remove ambiguous conversions and delegate it to the serde_json::Value itself.
Add struct JsonValueWrap { value: JsonValue } for use with Option
In schema, treat JsonValue as a special type, i.e. not as an alias to String, and forbid use of Option<JsonValue>.
Migration Guide
There is a breaking change for SDK developers. Apart from JsonString being renamed to JsonValue, it is also no longer an alias to String type, but instead is a special type JsonValue. SDK should treat it as a special case in a way that is suitable for their platform.
Binary and JSON serialisation compatibility is not broken. However, JSON form of ExecuteTrigger instruction and ExecuteTriggerEvent changed: its args field was an Option<JsonString> with ambiguous null value. Now it is Option<JsonValueWrap>, meaning that you need to use it this way:
Context
JsonString
is a type in the schema for arbitrary JSON values. In SCALE it is encoded as a string (hence the name), while in JSON it is inlined as any JSON value.There are a few issues:
Option<JsonString>
in JSON: it is impossible to distinguish betweenNone
andSome("null")
, since both serialize asnull
in actual JSON.JsonString
representation in JSON. In JSON it is not a string, which caused confusion for SDK developers.This PR fixes #4900 by disallowing
Option<JsonString>
and essentially forcing SDKs to handle JSON values as a special case and account for its differences in SCALE vs JSON.Solution
by these changes:
JsonString
toJsonValue
and make stronger emphasis on using the native Rust JSON type, i.e.serde_json::Value
. Remove ambiguous conversions and delegate it to theserde_json::Value
itself.struct JsonValueWrap { value: JsonValue }
for use withOption
JsonValue
as a special type, i.e. not as an alias toString
, and forbid use ofOption<JsonValue>
.Migration Guide
There is a breaking change for SDK developers. Apart from
JsonString
being renamed toJsonValue
, it is also no longer an alias toString
type, but instead is a special typeJsonValue
. SDK should treat it as a special case in a way that is suitable for their platform.Binary and JSON serialisation compatibility is not broken. However, JSON form of
ExecuteTrigger
instruction andExecuteTriggerEvent
changed: itsargs
field was anOption<JsonString>
with ambiguousnull
value. Now it isOption<JsonValueWrap>
, meaning that you need to use it this way:Review notes
primitives/json.rs
, then schema, then the restJsonValue
method names, especiallyget(&self) -> &Value
.Checklist
CONTRIBUTING.md
.