Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix toJson failing with repeated structured members at the same level #56

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 60 additions & 22 deletions ballerina/tests/to_json_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -223,17 +223,13 @@ type TestRecord4 record {|
function testToJsonWithCyclicValues() {
json[] v1 = [];
v1.push(v1);
json|error r1 = trap toJsonWithCyclicValues(v1);
test:assertTrue(r1 is error);
error r1Err = <error> r1;
test:assertEquals("the value has a cyclic reference", r1Err.message());
json|error r1 = toJsonWithCyclicValues(v1);
assertCyclicReferenceError(r1);

map<json> v2 = {};
v2["val"] = v2;
json|error r2 = trap toJsonWithCyclicValues(v2);
test:assertTrue(r2 is error);
error r2Err = <error> r2;
test:assertEquals("the value has a cyclic reference", r2Err.message());
json|error r2 = toJsonWithCyclicValues(v2);
assertCyclicReferenceError(r2);

TestRecord4 v3 = {
a: "a-v",
Expand All @@ -242,21 +238,17 @@ function testToJsonWithCyclicValues() {
d: []
};
v3.d.push(v3);
json|error r3 = trap toJsonWithCyclicValues(v3);
test:assertTrue(r3 is error);
error r3Err = <error> r3;
test:assertEquals("the value has a cyclic reference", r3Err.message());
json|error r3 = toJsonWithCyclicValues(v3);
assertCyclicReferenceError(r3);

table<record {readonly int id; string name; record {} details;}> key (id) v4 =
table [
{id: 1023, name: "Joy", details: {}}
];
record {} details = v4.get(1023).details;
details["tb"] = v4;
json|error r4 = trap toJsonWithCyclicValues(v4);
test:assertTrue(r4 is error);
error r4Err = <error> r4;
test:assertEquals("the value has a cyclic reference", r4Err.message());
json|error r4 = toJsonWithCyclicValues(v4);
assertCyclicReferenceError(r4);
}

@test:Config
Expand Down Expand Up @@ -285,6 +277,48 @@ function testToJsonWithoutCyclicValuesWithRepeatedSimpleValueMembers() {
test:assertNotExactEquals(jsonVal, jsonRes);
}

type GreetingConf record {|
readonly int id;
record {| string message; |} greeting;
record {| int count; int interval; |} repetition;
|};

@test:Config
function testToJsonWithoutCyclicValuesWithRepeatedStructuredMembers() {
map<json> greetingConf = {greeting: {message: "hello world"}, repetition: {count: 2, interval: 5}};
map<json>[] greetingConfs = [greetingConf, greetingConf];
json arrJson = toJson(greetingConfs);
test:assertEquals(greetingConfs, arrJson);
test:assertNotExactEquals(greetingConfs, arrJson);

GreetingConf gc = {
id: 1001,
greeting: {message: "hello world"},
repetition: {count: 2, interval: 5}
};
table<GreetingConf> tab = table [];
tab.put(gc);
tab.put({id: 1002, greeting: {message: "hello!"}, repetition: {count: 1, interval: 30}});
tab.put(gc);
json tabJson = toJson(tab);
test:assertEquals(<json[]> [
gc,
{id: 1002, greeting: {message: "hello!"}, repetition: {count: 1, interval: 30}},
gc
], tabJson);

int[] arr = [1, 2, 3];
map<int[]> mp = {
a: arr,
b: [],
c: [3, 5, 6, 7],
d: arr
};
json mapJson = toJson(mp);
test:assertEquals(mp, mapJson);
test:assertNotExactEquals(mp, mapJson);
}

@test:Config
function testToJsonWithCyclicValuesWithOtherSimpleValueMembers() {
byte byteVal = 3;
Expand All @@ -307,12 +341,16 @@ function testToJsonWithCyclicValuesWithOtherSimpleValueMembers() {
"p": false
};
jsonVal["q"] = jsonVal;
json|error r1 = trap toJsonWithCyclicValues(jsonVal);
test:assertTrue(r1 is error);
error r1Err = <error> r1;
test:assertEquals("the value has a cyclic reference", r1Err.message());
json|error r1 = toJsonWithCyclicValues(jsonVal);
assertCyclicReferenceError(r1);
}

function toJsonWithCyclicValues(anydata val) returns json|error {
return trap toJson(val);
}

function toJsonWithCyclicValues(anydata val) returns json {
return toJson(val);
function assertCyclicReferenceError(json|error res) {
test:assertTrue(res is error);
error err = <error> res;
test:assertEquals("the value has a cyclic reference", err.message());
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ public static Object toJson(Object value, Set<Object> visitedValues) {
int length = (int) listValue.getLength();
Object[] convertedValues = new Object[length];
for (int i = 0; i < length; i++) {
convertedValues[i] = toJson(listValue.get(i), visitedValues);
Object memValue = listValue.get(i);
convertedValues[i] = toJson(memValue, visitedValues);
visitedValues.remove(memValue);
}
return ValueCreator.createArrayValue(convertedValues, PredefinedTypes.TYPE_JSON_ARRAY);
}
Expand All @@ -122,6 +124,7 @@ public static Object toJson(Object value, Set<Object> visitedValues) {
for (BString entryKey : mapValue.getKeys()) {
Object entryValue = mapValue.get(entryKey);
jsonObject.put(getNameAnnotation(mapValue, entryKey), toJson(entryValue, visitedValues));
visitedValues.remove(entryValue);
}

return jsonObject;
Expand All @@ -134,6 +137,7 @@ public static Object toJson(Object value, Set<Object> visitedValues) {
int index = 0;
for (Object tableMember : tableValue.values()) {
convertedValues[index++] = toJson(tableMember, visitedValues);
visitedValues.remove(tableMember);
}
return ValueCreator.createArrayValue(convertedValues, PredefinedTypes.TYPE_JSON_ARRAY);
}
Expand Down
Loading