diff --git a/builtin/json.mbt b/builtin/json.mbt index 47654bed9..c9d4a4b7d 100644 --- a/builtin/json.mbt +++ b/builtin/json.mbt @@ -125,7 +125,7 @@ pub fn Map::to_json[K : Show, V : ToJson](self : Map[K, V]) -> Json { pub fn Option::to_json[T : ToJson](self : T?) -> Json { match self { None => Null - Some(value) => value.to_json() + Some(value) => [value.to_json()] } } diff --git a/json/from_json.mbt b/json/from_json.mbt index 08e82d6ac..988d20739 100644 --- a/json/from_json.mbt +++ b/json/from_json.mbt @@ -145,7 +145,8 @@ pub impl[V : FromJson] FromJson for Map[String, V] with from_json(json, path) { pub impl[T : FromJson] FromJson for T? with from_json(json, path) { match json { Null => None - _ => Some(FromJson::from_json!(json, path)) + Array([value]) => Some(FromJson::from_json!(value, path.add_index(0))) + _ => decode_error!(path, "Option::from_json: expected array or null") } } diff --git a/json/from_json_test.mbt b/json/from_json_test.mbt index beaeda3c3..caf624555 100644 --- a/json/from_json_test.mbt +++ b/json/from_json_test.mbt @@ -314,6 +314,12 @@ test "Option" { let u = Some(1).to_json() let v : Int? = @json.from_json!(u) inspect!(v, content="Some(1)") + let nested : Json = (Some(None) : Unit??).to_json() + let v : Unit?? = @json.from_json!(nested) + inspect!(v, content="Some(None)") + let nested : Json = (Some(Some(None)) : Unit???).to_json() + let v : Unit??? = @json.from_json!(nested) + inspect!(v, content="Some(Some(None))") } test "Result" { diff --git a/json/to_json_test.mbt b/json/to_json_test.mbt index 255d1c8bb..1dac9625a 100644 --- a/json/to_json_test.mbt +++ b/json/to_json_test.mbt @@ -129,9 +129,40 @@ test "Map::to_json" { ) } +struct Opt { + x : Int? + t : Int?? +} derive(ToJson) + test "Option::to_json" { - inspect!((Some(42) : Int?).to_json(), content="Number(42)") + inspect!((Some(42) : Int?).to_json(), content="Array([Number(42)])") inspect!((None : Int?).to_json(), content="Null") + inspect!((Some(None) : Unit??).to_json(), content="Array([Null])") + inspect!( + (Some(Some(None)) : Unit???).to_json(), + content="Array([Array([Null])])", + ) + let opt = { x: Some(42), t: Some(Some(42)) } + inspect!( + opt.to_json(), + content= + #|Object({"x": Array([Number(42)]), "t": Array([Array([Number(42)])])}) + , + ) + let opt = { x: None, t: None } + inspect!( + opt.to_json(), + content= + #|Object({"x": Null, "t": Null}) + , + ) + let opt = { x: None, t: Some(None) } + inspect!( + opt.to_json(), + content= + #|Object({"x": Null, "t": Array([Null])}) + , + ) } test "Tuple::to_json" {