diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4c92918..404b558 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # See: https://help.github.com/articles/about-codeowners/ # These owners will be the default owners for everything in the repo. -* @gimantha @MaryamZi @hasithaa +* @gimantha @MaryamZi @hasithaa @SasinduDilshara diff --git a/ballerina/tests/from_json_string_test.bal b/ballerina/tests/from_json_string_test.bal index bb4902e..e46ea48 100644 --- a/ballerina/tests/from_json_string_test.bal +++ b/ballerina/tests/from_json_string_test.bal @@ -60,6 +60,61 @@ isolated function testSimpleJsonStringToRecord() returns Error? { test:assertEquals(recC.get("b"), 1); } +@test:Config +isolated function testSimpleJsonStringToRecord2() returns Error? { + string user = string `{"id": 4012}`; + ReadOnlyUserRecord r = check parseString(user); + test:assertEquals(r, {id: 4012}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord3() returns Error? { + string user = string `{"id": 4012, "name": {"firstname": "John", "lastname": "Doe"}, "age": 27}`; + ReadOnlyUserRecord2 r = check parseString(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord4() returns Error? { + string user = string `{"id": 4012, "name": {"firstname": "John", "lastname": "Doe"}, "age": 27}`; + UserRecord3 r = check parseString(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord5() returns Error? { + string user = string `{"id": 4012, "name": {"firstname": "John", "lastname": "Doe"}, "age": 27}`; + ReadOnlyUserRecord2 r = check parseString(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord6() returns Error? { + string user = string `{"ids": [4012, 4013], "names": [{"firstname": "John", "lastname": "Doe"}, + {"firstname": "Jane", "lastname": "Doe"}], "age": 27}`; + ReadOnlyUsersRecord3 r = check parseString(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord7() returns Error? { + string user = string `{"ids": [4012, 4013], "names": [{"firstname": "John", "lastname": "Doe"}, + {"firstname": "Jane", "lastname": "Doe"}], "age": 27}`; + ReadOnlyUsersRecord4 r = check parseString(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); +} + +@test:Config +isolated function testSimpleJsonStringToRecord8() returns Error? { + string user = string `{"ids": [4012, 4013], "names": [{"firstname": "John", "lastname": "Doe"}, + {"firstname": "Jane", "lastname": "Doe"}], "age": 27}`; + ReadOnlyUsersRecord5 r = check parseString(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); +} + @test:Config isolated function testSimpleJsonStringToRecordWithProjection() returns Error? { string str = string `{"a": "hello", "b": 1}`; diff --git a/ballerina/tests/from_json_test.bal b/ballerina/tests/from_json_test.bal index 8be3947..38bd754 100644 --- a/ballerina/tests/from_json_test.bal +++ b/ballerina/tests/from_json_test.bal @@ -67,6 +67,121 @@ isolated function testSimpleJsonToRecord() returns Error? { test:assertEquals(recC.get("b"), 1); } +type ReadOnlyUserRecord readonly & record {| + int id; +|}; + +@test:Config +isolated function testSimpleJsonToRecord2() returns Error? { + json user = {id: 4012}; + ReadOnlyUserRecord r = check parseAsType(user); + test:assertEquals(r, {id: 4012}); +} + +public type ReadonlyUserId readonly & int; + +public type ReadonlyUserName readonly & record { + string firstname; + string lastname; +}; + +type ReadOnlyUserRecord2 readonly & record {| + ReadonlyUserId id; + ReadonlyUserName name; + int age; +|}; + +@test:Config +isolated function testSimpleJsonToRecord3() returns Error? { + json user = {id: 4012, name: {firstname: "John", lastname: "Doe"}, age: 27}; + ReadOnlyUserRecord2 r = check parseAsType(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +type UserRecord3 ReadOnlyUserRecord2; + +@test:Config +isolated function testSimpleJsonToRecord4() returns Error? { + json user = {id: 4012, name: {firstname: "John", lastname: "Doe"}, age: 27}; + UserRecord3 r = check parseAsType(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +@test:Config +isolated function testSimpleJsonToRecord5() returns Error? { + ReadonlyUserName username = {firstname: "John", lastname: "Doe"}; + record{string firstname; string lastname;} nameRec = username; + json user = {id: 4012, name: nameRec.toJson(), age: 27}; + ReadOnlyUserRecord2 r = check parseAsType(user); + test:assertEquals(r, {id: 4012, age: 27, name: {firstname: "John", lastname: "Doe"}}); +} + +type ReadOnlyUsersRecord3 readonly & record {| + ReadonlyUserId[] ids; + ReadonlyUserName[] names; +|}; + +@test:Config +isolated function testSimpleJsonToRecord6() returns Error? { + json user = {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}], age: 27}; + ReadOnlyUsersRecord3 r = check parseAsType(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); + test:assertTrue(r.ids is readonly); + test:assertTrue(r.names is readonly); + test:assertTrue(r is ReadOnlyUsersRecord5 & readonly); +} + +type ReadOnlyUsersRecord4 readonly & record {| + ReadonlyUserId[] & readonly ids; + ReadonlyUserName[] & readonly names; +|}; + +@test:Config +isolated function testSimpleJsonToRecord7() returns Error? { + json user = {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}], age: 27}; + ReadOnlyUsersRecord4 r = check parseAsType(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); +} + +type ReadOnlyUsersRecord5 record {| + ReadonlyUserId[] & readonly ids; + ReadonlyUserName[] & readonly names; +|}; + +@test:Config +isolated function testSimpleJsonToRecord8() returns Error? { + json user = {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}], age: 27}; + ReadOnlyUsersRecord5 r = check parseAsType(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); + test:assertTrue(r.ids is readonly); + test:assertTrue(r.names is readonly); +} + +type ReadonlyUserIdArray ReadonlyUserId[] & readonly; +type ReadonlyUserNameArray ReadonlyUserName[] & readonly; + +type ReadOnlyUsersRecord6 record {| + ReadonlyUserIdArray ids; + ReadonlyUserNameArray names; +|}; + +@test:Config +isolated function testSimpleJsonToRecord9() returns Error? { + json user = {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}], age: 27}; + ReadOnlyUsersRecord6 r = check parseAsType(user); + test:assertEquals(r, {ids: [4012, 4013], names: [{firstname: "John", lastname: "Doe"}, + {firstname: "Jane", lastname: "Doe"}]}); + test:assertTrue(r.ids is readonly); + test:assertTrue(r.names is readonly); +} + @test:Config isolated function testSimpleJsonToRecordWithProjection() returns Error? { json j = {"a": "hello", "b": 1}; diff --git a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonCreator.java b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonCreator.java index 37f4978..f84f31f 100644 --- a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonCreator.java +++ b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonCreator.java @@ -395,6 +395,9 @@ static Type getMemberType(Type expectedType, int index, boolean allowDataProject } Type referredType = TypeUtils.getReferredType(expectedType); + if (referredType.getTag() == TypeTags.INTERSECTION_TAG) { + return getMemberType(((IntersectionType) referredType).getEffectiveType(), index, allowDataProjection); + } if (referredType.getTag() == TypeTags.ARRAY_TAG) { ArrayType arrayType = (ArrayType) referredType; if (arrayType.getState() == ArrayType.ArrayState.OPEN diff --git a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonParser.java b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonParser.java index ad911a2..a3c4de7 100644 --- a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonParser.java +++ b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonParser.java @@ -249,7 +249,7 @@ public Object execute(Reader reader, BMap options, Type type) t } case TypeTags.INTERSECTION_TAG -> { Type effectiveType = ((IntersectionType) type).getEffectiveType(); - if (!SymbolFlags.isFlagOn(SymbolFlags.READONLY, effectiveType.getFlags())) { + if (!effectiveType.isReadOnly()) { throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE, type); } diff --git a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonTraverse.java b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonTraverse.java index ff219cf..a4a0efc 100644 --- a/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonTraverse.java +++ b/native/src/main/java/io/ballerina/lib/data/jsondata/json/JsonTraverse.java @@ -169,7 +169,7 @@ private Object traverseJson(Object json, Type type) { } case TypeTags.INTERSECTION_TAG -> { Type effectiveType = ((IntersectionType) referredType).getEffectiveType(); - if (!SymbolFlags.isFlagOn(SymbolFlags.READONLY, effectiveType.getFlags())) { + if (!effectiveType.isReadOnly()) { throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE, type); } for (Type constituentType : ((IntersectionType) referredType).getConstituentTypes()) {