This started in #225
Goal: JSON Serialize / Deserialize WIT Records based on WIT field names.
Progress
Approach
Centralize JSON serialization in the cm package, keeping codegen changes to a minimum.
Given a complex record type:
record response {
headers: list<tuple<string, list<string>>>,
http-code: u16,
body: response-body
}
variant response-body {
ok(list<list-element>),
err(function-error),
platform-err(platform-error)
}
record list-element {
optional-int: option<u64>,
optional-bool: option<bool>,
}
record function-error {
error: string
}
record platform-error {
code: string,
message: string
}
and filling it up:
hdrVals := cm.ToList([]string{"value1", "value2"})
hdrTuple := cm.Tuple[string, cm.List[string]]{
F0: "header-name",
F1: hdrVals,
}
headers := cm.ToList([]cm.Tuple[string, cm.List[string]]{hdrTuple})
v := somefunctioninterface.Response{
Headers: headers,
HTTPCode: 200,
Body: somefunctioninterface.ResponseBodyErr(somefunctioninterface.FunctionError{Error: "failed"}),
}
We should serialize it to JSON as:
{"headers":[["header-name",["value1","value2"]]],"http-code":200,"body":{"err":{"error":"failed"}}}
For comparison, this is what is produced today:
{"Headers":{},"Body":{"RequiredParam":"required","OptionalParam":{}}}
Type encoding
Whenever possible, reuse standard mappings. string -> string, u32 -> uint32, etc.
Tuple handling
Tuples are encoded as json arrays with explicit nulls.
Tuple[string,int] -> [ "some string", 42 ]
Tuple3[string, *string, int] -> [ "some string", null, 42 ]
Variant handling
Variants are encoded as json dictionaries, so they can carry the variant data.
record somerecord {
myvariant: somevar,
}
variant somevar {
ok,
err(string),
}
// JSON
{ "myvariant": { "ok": true }}
{ "myvariant": { "error": "error value" }}
Option handling
Options rely on explicit null for the "None" case.
{ "myoptional": null } // cm.None
{ "myoptional": "this" } // cm.Option[string]
Questions
Zero Value Variants
Today they end up with tag = 0, this impacts de-serialization of variants. We need the ability to distinct between:
var v Variant
v := NewVariantWithZeroTagValue()
v := Some(NewVariantWithZeroTagValue)
atm only the Some() path de-serializes correctly ( pointers ).
This started in #225
Goal: JSON Serialize / Deserialize WIT Records based on WIT field names.
Progress
record- wit/bindgen: Add JSON tag to Record structs #265list- cm: Implement json Marshal/Unmarshal for List type #266enumtuplevariantresultoptionresourcehandle types (decide behavior)error-contextstreamfutureApproach
Centralize JSON serialization in the
cmpackage, keeping codegen changes to a minimum.Given a complex record type:
and filling it up:
We should serialize it to JSON as:
For comparison, this is what is produced today:
Type encoding
Whenever possible, reuse standard mappings. string -> string, u32 -> uint32, etc.
Tuple handling
Tuples are encoded as json arrays with explicit
nulls.Variant handling
Variants are encoded as json dictionaries, so they can carry the variant data.
Option handling
Options rely on explicit
nullfor the "None" case.Questions
Zero Value Variants
Today they end up with
tag = 0, this impacts de-serialization of variants. We need the ability to distinct between:var v Variantv := NewVariantWithZeroTagValue()v := Some(NewVariantWithZeroTagValue)atm only the
Some()path de-serializes correctly ( pointers ).