diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml
index b2be744..3cd78f4 100644
--- a/ballerina/Dependencies.toml
+++ b/ballerina/Dependencies.toml
@@ -12,6 +12,7 @@ org = "ballerina"
 name = "data.jsondata"
 version = "0.1.0"
 dependencies = [
+	{org = "ballerina", name = "file"},
 	{org = "ballerina", name = "io"},
 	{org = "ballerina", name = "jballerina.java"},
 	{org = "ballerina", name = "lang.float"},
@@ -24,6 +25,21 @@ modules = [
 	{org = "ballerina", packageName = "data.jsondata", moduleName = "data.jsondata"}
 ]
 
+[[package]]
+org = "ballerina"
+name = "file"
+version = "1.9.0"
+scope = "testOnly"
+dependencies = [
+	{org = "ballerina", name = "io"},
+	{org = "ballerina", name = "jballerina.java"},
+	{org = "ballerina", name = "os"},
+	{org = "ballerina", name = "time"}
+]
+modules = [
+	{org = "ballerina", packageName = "file", moduleName = "file"}
+]
+
 [[package]]
 org = "ballerina"
 name = "io"
@@ -120,6 +136,16 @@ modules = [
 	{org = "ballerina", packageName = "lang.value", moduleName = "lang.value"}
 ]
 
+[[package]]
+org = "ballerina"
+name = "os"
+version = "1.8.0"
+scope = "testOnly"
+dependencies = [
+	{org = "ballerina", name = "io"},
+	{org = "ballerina", name = "jballerina.java"}
+]
+
 [[package]]
 org = "ballerina"
 name = "test"
@@ -134,3 +160,12 @@ modules = [
 	{org = "ballerina", packageName = "test", moduleName = "test"}
 ]
 
+[[package]]
+org = "ballerina"
+name = "time"
+version = "2.4.0"
+scope = "testOnly"
+dependencies = [
+	{org = "ballerina", name = "jballerina.java"}
+]
+
diff --git a/ballerina/build.gradle b/ballerina/build.gradle
index b2fad92..bcfbad6 100644
--- a/ballerina/build.gradle
+++ b/ballerina/build.gradle
@@ -17,19 +17,8 @@
 
 import org.apache.tools.ant.taskdefs.condition.Os
 
-buildscript {
-    repositories {
-        maven {
-            url = 'https://maven.pkg.github.com/ballerina-platform/plugin-gradle'
-            credentials {
-                username System.getenv("packageUser")
-                password System.getenv("packagePAT")
-            }
-        }
-    }
-    dependencies {
-        classpath "io.ballerina:plugin-gradle:${project.ballerinaGradlePluginVersion}"
-    }
+plugins {
+    id 'io.ballerina.plugin'
 }
 
 description = 'Ballerina - Data JSON Module'
@@ -57,8 +46,6 @@ def stripBallerinaExtensionVersion(String extVersion) {
     }
 }
 
-apply plugin: 'io.ballerina.plugin'
-
 ballerina {
     testCoverageParam = "--code-coverage --coverage-format=xml --includes=io.ballerina.lib.data.*:ballerina.*"
     packageOrganization = packageOrg
diff --git a/ballerina/json_api.bal b/ballerina/json_api.bal
index 4720d71..c987814 100644
--- a/ballerina/json_api.bal
+++ b/ballerina/json_api.bal
@@ -58,6 +58,16 @@ public isolated function parseStream(stream<byte[], error?> s, Options options =
 public isolated function toJson(anydata v)
         returns json|Error = @java:Method {'class: "io.ballerina.lib.data.jsondata.json.Native"} external;
 
+# Prettifies a `json` value to print it.
+#
+# + value - The `json` value to be prettified
+# + indentation - The number of spaces for an indentation
+# + return - The prettified `json` as a string
+public isolated function prettify(json value, int indentation = 4) returns string {
+    string indent = getIndentation(indentation);
+    return prettifyJson(value, indent, 0);
+}
+
 # Represent the options that can be used to modify the behaviour of the projection.
 #
 # + allowDataProjection - Enable or disable projection
diff --git a/ballerina/tests/prettify_test.bal b/ballerina/tests/prettify_test.bal
new file mode 100644
index 0000000..63628c6
--- /dev/null
+++ b/ballerina/tests/prettify_test.bal
@@ -0,0 +1,224 @@
+// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
+//
+// WSO2 LLC. licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except
+// in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import ballerina/test;
+
+@test:Config {
+    groups: ["prettify", "string"]
+}
+function testStringValue() returns error? {
+    json value = "Sam";
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("string_value.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "int"]
+}
+function testIntValue() returns error? {
+    json value = 515;
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("int_value.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "boolean"]
+}
+function testBooleanValue() returns error? {
+    json value = false;
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("boolean_value.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "null"]
+}
+function testNullValue() returns error? {
+    json value = null;
+    string actual = prettify(value);
+    string expected = " null";
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "null"]
+}
+isolated function testNullInMap() returns error? {
+    json value = {
+        name: "Sam",
+        age: null,
+        address: {
+            number: 308,
+            street: "Negra Arroyo Lane",
+            city: null
+        }
+    };
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("null_in_map.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "array"]
+}
+function testStringArray() returns error? {
+    json value = ["sam", "bam", "tan"];
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("string_array.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "array"]
+}
+function testEmptyArray() returns error? {
+    json value = [];
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("empty_array.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testEmptyMap() returns error? {
+    json value = {};
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("empty_map.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testArrayOfEmptyMaps() returns error? {
+    json value = [
+        {},
+        {},
+        {}
+    ];
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("array_of_empty_maps.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testMapWithStringField() returns error? {
+    json value = {
+        name: "Walter White"
+    };
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("map_with_string_field.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testMapWithMultipleStringFields() returns error? {
+    json value = {
+        name: "Walter White",
+        subject: "Chemistry",
+        city: "Albequerque"
+    };
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("map_with_multiple_string_fields.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testMap() returns error? {
+    json value = {
+        person: {
+            name: "Walter White",
+            age: 51,
+            address: {
+                number: 308,
+                street: "Negra Arroyo Lane",
+                city: "Albequerque"
+            }
+        }
+    };
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("map.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "map"]
+}
+function testArrayOfMap() returns error? {
+    json value = [
+        {
+            name: "Walter White",
+            age: 51,
+            address: {
+                number: 308,
+                street: "Negra Arroyo Lane",
+                city: "Albequerque"
+            }
+        },
+        {
+            name: "Jesse Pinkman",
+            age: 26,
+            address: {
+                number: 9809,
+                street: "Margo Street",
+                city: "Albequerque"
+            }
+        }
+    ];
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("array_of_map.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "array", "map"]
+}
+function testComplexExample() returns error? {
+    json value = check getJsonContentFromFile("complex_example.json");
+    string actual = prettify(value);
+    string expected = check getStringContentFromFile("complex_example.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "array", "map"]
+}
+function testComplexExampleWithCustomIndentation() returns error? {
+    json value = check getJsonContentFromFile("complex_example.json");
+    string actual = prettify(value, 2);
+    string expected = check getStringContentFromFile("complex_example_with_custom_indentation.json");
+    test:assertEquals(actual, expected);
+}
+
+@test:Config {
+    groups: ["prettify", "array", "map"]
+}
+function testComplexExampleWithCustomIndentationInvalidTest() returns error? {
+    json value = check getJsonContentFromFile("complex_example.json");
+    string actual = prettify(value, 2);
+    string expected = check getStringContentFromFile("complex_example.json");
+    test:assertNotEquals(actual, expected);
+}
diff --git a/ballerina/tests/resources/expected_results/array_of_empty_maps.json b/ballerina/tests/resources/expected_results/array_of_empty_maps.json
new file mode 100644
index 0000000..46133e6
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/array_of_empty_maps.json
@@ -0,0 +1,5 @@
+[
+    {},
+    {},
+    {}
+]
diff --git a/ballerina/tests/resources/expected_results/array_of_map.json b/ballerina/tests/resources/expected_results/array_of_map.json
new file mode 100644
index 0000000..6f8c3b8
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/array_of_map.json
@@ -0,0 +1,20 @@
+[
+    {
+        "name": "Walter White",
+        "age": 51,
+        "address": {
+            "number": 308,
+            "street": "Negra Arroyo Lane",
+            "city": "Albequerque"
+        }
+    },
+    {
+        "name": "Jesse Pinkman",
+        "age": 26,
+        "address": {
+            "number": 9809,
+            "street": "Margo Street",
+            "city": "Albequerque"
+        }
+    }
+]
diff --git a/ballerina/tests/resources/expected_results/boolean_value.json b/ballerina/tests/resources/expected_results/boolean_value.json
new file mode 100644
index 0000000..c508d53
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/boolean_value.json
@@ -0,0 +1 @@
+false
diff --git a/ballerina/tests/resources/expected_results/complex_example.json b/ballerina/tests/resources/expected_results/complex_example.json
new file mode 100644
index 0000000..c8403ff
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/complex_example.json
@@ -0,0 +1,87 @@
+{
+    "colors": [
+        {
+            "color": "black",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    255,
+                    255,
+                    1
+                ],
+                "hex": "#000"
+            }
+        },
+        {
+            "color": "white",
+            "category": "value",
+            "code": {
+                "rgba": [
+                    0,
+                    0,
+                    0,
+                    1
+                ],
+                "hex": "#FFF"
+            }
+        },
+        {
+            "color": "red",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    0,
+                    0,
+                    1
+                ],
+                "hex": "#FF0"
+            }
+        },
+        {
+            "color": "blue",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    0,
+                    0,
+                    255,
+                    1
+                ],
+                "hex": "#00F"
+            }
+        },
+        {
+            "color": "yellow",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    255,
+                    0,
+                    1
+                ],
+                "hex": "#FF0"
+            }
+        },
+        {
+            "color": "green",
+            "category": "hue",
+            "type": "secondary",
+            "code": {
+                "rgba": [
+                    0,
+                    255,
+                    0,
+                    1
+                ],
+                "hex": "#0F0"
+            }
+        }
+    ]
+}
diff --git a/ballerina/tests/resources/expected_results/complex_example_with_custom_indentation.json b/ballerina/tests/resources/expected_results/complex_example_with_custom_indentation.json
new file mode 100644
index 0000000..ea29bd3
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/complex_example_with_custom_indentation.json
@@ -0,0 +1,87 @@
+{
+  "colors": [
+    {
+      "color": "black",
+      "category": "hue",
+      "type": "primary",
+      "code": {
+        "rgba": [
+          255,
+          255,
+          255,
+          1
+        ],
+        "hex": "#000"
+      }
+    },
+    {
+      "color": "white",
+      "category": "value",
+      "code": {
+        "rgba": [
+          0,
+          0,
+          0,
+          1
+        ],
+        "hex": "#FFF"
+      }
+    },
+    {
+      "color": "red",
+      "category": "hue",
+      "type": "primary",
+      "code": {
+        "rgba": [
+          255,
+          0,
+          0,
+          1
+        ],
+        "hex": "#FF0"
+      }
+    },
+    {
+      "color": "blue",
+      "category": "hue",
+      "type": "primary",
+      "code": {
+        "rgba": [
+          0,
+          0,
+          255,
+          1
+        ],
+        "hex": "#00F"
+      }
+    },
+    {
+      "color": "yellow",
+      "category": "hue",
+      "type": "primary",
+      "code": {
+        "rgba": [
+          255,
+          255,
+          0,
+          1
+        ],
+        "hex": "#FF0"
+      }
+    },
+    {
+      "color": "green",
+      "category": "hue",
+      "type": "secondary",
+      "code": {
+        "rgba": [
+          0,
+          255,
+          0,
+          1
+        ],
+        "hex": "#0F0"
+      }
+    }
+  ]
+}
diff --git a/ballerina/tests/resources/expected_results/empty_array.json b/ballerina/tests/resources/expected_results/empty_array.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/empty_array.json
@@ -0,0 +1 @@
+[]
diff --git a/ballerina/tests/resources/expected_results/empty_map.json b/ballerina/tests/resources/expected_results/empty_map.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/empty_map.json
@@ -0,0 +1 @@
+{}
diff --git a/ballerina/tests/resources/expected_results/int_value.json b/ballerina/tests/resources/expected_results/int_value.json
new file mode 100644
index 0000000..3cda32f
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/int_value.json
@@ -0,0 +1 @@
+515
diff --git a/ballerina/tests/resources/expected_results/map.json b/ballerina/tests/resources/expected_results/map.json
new file mode 100644
index 0000000..670754a
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/map.json
@@ -0,0 +1,11 @@
+{
+    "person": {
+        "name": "Walter White",
+        "age": 51,
+        "address": {
+            "number": 308,
+            "street": "Negra Arroyo Lane",
+            "city": "Albequerque"
+        }
+    }
+}
diff --git a/ballerina/tests/resources/expected_results/map_with_multiple_string_fields.json b/ballerina/tests/resources/expected_results/map_with_multiple_string_fields.json
new file mode 100644
index 0000000..579d119
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/map_with_multiple_string_fields.json
@@ -0,0 +1,5 @@
+{
+    "name": "Walter White",
+    "subject": "Chemistry",
+    "city": "Albequerque"
+}
diff --git a/ballerina/tests/resources/expected_results/map_with_string_field.json b/ballerina/tests/resources/expected_results/map_with_string_field.json
new file mode 100644
index 0000000..9363606
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/map_with_string_field.json
@@ -0,0 +1,3 @@
+{
+    "name": "Walter White"
+}
diff --git a/ballerina/tests/resources/expected_results/null_in_map.json b/ballerina/tests/resources/expected_results/null_in_map.json
new file mode 100644
index 0000000..73d632a
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/null_in_map.json
@@ -0,0 +1,9 @@
+{
+    "name": "Sam",
+    "age": null,
+    "address": {
+        "number": 308,
+        "street": "Negra Arroyo Lane",
+        "city": null
+    }
+}
diff --git a/ballerina/tests/resources/expected_results/string_array.json b/ballerina/tests/resources/expected_results/string_array.json
new file mode 100644
index 0000000..3e5eed7
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/string_array.json
@@ -0,0 +1,5 @@
+[
+    "sam",
+    "bam",
+    "tan"
+]
diff --git a/ballerina/tests/resources/expected_results/string_value.json b/ballerina/tests/resources/expected_results/string_value.json
new file mode 100644
index 0000000..6b5dec0
--- /dev/null
+++ b/ballerina/tests/resources/expected_results/string_value.json
@@ -0,0 +1 @@
+"Sam"
diff --git a/ballerina/tests/resources/input_files/complex_example.json b/ballerina/tests/resources/input_files/complex_example.json
new file mode 100644
index 0000000..c8403ff
--- /dev/null
+++ b/ballerina/tests/resources/input_files/complex_example.json
@@ -0,0 +1,87 @@
+{
+    "colors": [
+        {
+            "color": "black",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    255,
+                    255,
+                    1
+                ],
+                "hex": "#000"
+            }
+        },
+        {
+            "color": "white",
+            "category": "value",
+            "code": {
+                "rgba": [
+                    0,
+                    0,
+                    0,
+                    1
+                ],
+                "hex": "#FFF"
+            }
+        },
+        {
+            "color": "red",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    0,
+                    0,
+                    1
+                ],
+                "hex": "#FF0"
+            }
+        },
+        {
+            "color": "blue",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    0,
+                    0,
+                    255,
+                    1
+                ],
+                "hex": "#00F"
+            }
+        },
+        {
+            "color": "yellow",
+            "category": "hue",
+            "type": "primary",
+            "code": {
+                "rgba": [
+                    255,
+                    255,
+                    0,
+                    1
+                ],
+                "hex": "#FF0"
+            }
+        },
+        {
+            "color": "green",
+            "category": "hue",
+            "type": "secondary",
+            "code": {
+                "rgba": [
+                    0,
+                    255,
+                    0,
+                    1
+                ],
+                "hex": "#0F0"
+            }
+        }
+    ]
+}
diff --git a/ballerina/tests/utils.bal b/ballerina/tests/utils.bal
new file mode 100644
index 0000000..31286a3
--- /dev/null
+++ b/ballerina/tests/utils.bal
@@ -0,0 +1,28 @@
+// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
+//
+// WSO2 LLC. licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except
+// in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import ballerina/file;
+import ballerina/io;
+
+isolated function getStringContentFromFile(string fileName) returns string|error {
+    string path = check file:joinPath("tests", "resources", "expected_results", fileName);
+    return io:fileReadString(path);
+}
+
+isolated function getJsonContentFromFile(string fileName) returns json|error {
+    string path = check file:joinPath("tests", "resources", "input_files", fileName);
+    return io:fileReadJson(path);
+}
diff --git a/ballerina/utils.bal b/ballerina/utils.bal
new file mode 100644
index 0000000..918d139
--- /dev/null
+++ b/ballerina/utils.bal
@@ -0,0 +1,105 @@
+// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
+//
+// WSO2 LLC. licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except
+// in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+isolated function prettifyJson(json value, string indentation, int level, boolean isMapField = false) returns string {
+    if value == () {
+        return " null";
+    } else if value is map<json> {
+        return prettifyJsonMap(value, indentation, level, isMapField);
+    } else if value is json[] {
+        return prettifyJsonArray(value, indentation, level, isMapField);
+    } else {
+        return prettifyJsonField(value, indentation, level, isMapField);
+    }
+}
+
+isolated function prettifyJsonMap(map<json> value, string indentation, int level, boolean isMapField) returns string {
+    string initialIndentation = getInitialIndentation(indentation, level, isMapField);
+    string result = string `${initialIndentation}{`;
+    boolean isEmptyMap = value.keys().length() == 0;
+    if !isEmptyMap {
+        result += "\n";
+    }
+
+    int fieldLevel = level + 1;
+    string fieldIndentation = getIndentationForLevel(indentation, fieldLevel);
+    int length = value.length();
+    int i = 1;
+    foreach string key in value.keys() {
+        string fieldValue = prettifyJson(value.get(key), indentation, fieldLevel, true);
+        string line = string `${fieldIndentation}"${key}":${fieldValue}`;
+        result += line;
+        if i != length {
+            result += ",";
+        }
+        result += "\n";
+        i += 1;
+    }
+
+    if !isEmptyMap {
+        result += getIndentationForLevel(indentation, level);
+    }
+    result += "}";
+    return result;
+}
+
+isolated function prettifyJsonArray(json[] array, string indentation, int level, boolean isMapField) returns string {
+    string initialIndentation = getInitialIndentation(indentation, level, isMapField);
+    string result = string `${initialIndentation}[`;
+
+    boolean isEmptyArray = array.length() == 0;
+    if !isEmptyArray {
+        result += "\n";
+    }
+
+    int elementLevel = level + 1;
+    string[] elements = [];
+    foreach json value in array {
+        elements.push(prettifyJson(value, indentation, elementLevel));
+    }
+    string separator = ",\n";
+    result += 'string:'join(separator, ...elements);
+
+    if !isEmptyArray {
+        result += "\n" + getIndentationForLevel(indentation, level);
+    }
+    return string `${result}]`;
+}
+
+isolated function getIndentation(int indentation) returns string {
+    string result = "";
+    foreach int i in 0 ..< indentation {
+        result += " ";
+    }
+    return result;
+}
+
+isolated function getIndentationForLevel(string indentation, int level) returns string {
+    string result = "";
+    foreach int i in 0 ..< level {
+        result += indentation;
+    }
+    return result;
+}
+
+isolated function getInitialIndentation(string indentation, int level, boolean isMapField) returns string {
+    return isMapField ? " " : getIndentationForLevel(indentation, level);
+}
+
+isolated function prettifyJsonField(json value, string indentation, int level, boolean isMapField) returns string {
+    string initialIndentation = getInitialIndentation(indentation, level, isMapField);
+    return string `${initialIndentation}${value.toJsonString()}`;
+}
diff --git a/build.gradle b/build.gradle
index 2551eb1..dc59376 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,10 +17,10 @@
  */
 
 plugins {
-    id "com.github.spotbugs" version "${githubSpotbugsVersion}"
-    id "com.github.johnrengelman.shadow" version "${githubJohnrengelmanShadowVersion}"
-    id "de.undercouch.download" version "${underCouchDownloadVersion}"
-    id "net.researchgate.release" version "${researchgateReleaseVersion}"
+    id "com.github.spotbugs"
+    id "com.github.johnrengelman.shadow"
+    id "de.undercouch.download"
+    id "net.researchgate.release"
 }
 
 allprojects {
@@ -67,7 +67,10 @@ subprojects {
 
     dependencies {
         /* Standard libraries */
+        ballerinaStdLibs "io.ballerina.stdlib:file-ballerina:${stdlibFileVersion}"
         ballerinaStdLibs "io.ballerina.stdlib:io-ballerina:${stdlibIoVersion}"
+        ballerinaStdLibs "io.ballerina.stdlib:os-ballerina:${stdlibOsVersion}"
+        ballerinaStdLibs "io.ballerina.stdlib:time-ballerina:${stdlibTimeVersion}"
     }
 }
 
diff --git a/compiler-plugin-test/build.gradle b/compiler-plugin-test/build.gradle
index efc4838..c3862bf 100644
--- a/compiler-plugin-test/build.gradle
+++ b/compiler-plugin-test/build.gradle
@@ -83,6 +83,18 @@ test {
     systemProperty "ballerina.offline.flag", "true"
     useTestNG()
     finalizedBy jacocoTestReport
+
+    testLogging {
+        exceptionFormat = "full"
+        afterSuite { desc, result ->
+            if (!desc.parent) { // will match the outermost suite
+                def output = "Compiler Plugin Tests: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
+                def startItem = '|  ', endItem = '  |'
+                def repeatLength = startItem.length() + output.length() + endItem.length()
+                println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
+            }
+        }
+    }
 }
 
 jacocoTestReport {
diff --git a/gradle.properties b/gradle.properties
index 96e4fcc..1c53816 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -7,12 +7,16 @@ checkstyleToolVersion=10.12.0
 puppycrawlCheckstyleVersion=10.12.0
 testngVersion=7.6.1
 slf4jVersion=2.0.7
-githubSpotbugsVersion=5.0.14
-githubJohnrengelmanShadowVersion=8.1.1
-underCouchDownloadVersion=4.0.4
-researchgateReleaseVersion=2.8.0
+spotbugsVersion=5.0.14
+shadowJarPluginVersion=8.1.1
+downloadPluginVersion=4.0.4
+releasePluginVersion=2.8.0
 ballerinaGradlePluginVersion=2.0.1
 javaJsonPathVersion=2.9.0
 javaJsonSmartVersion=2.4.11
 javaAccessorsSmartVersion=2.4.7
+
+stdlibFileVersion=1.9.0
 stdlibIoVersion=1.6.0
+stdlibOsVersion=1.8.0
+stdlibTimeVersion=2.4.0
diff --git a/settings.gradle b/settings.gradle
index 3061afb..80e39d1 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -16,6 +16,26 @@
  * under the License.
  */
 
+pluginManagement {
+    plugins {
+        id "com.github.spotbugs" version "${spotbugsVersion}"
+        id "com.github.johnrengelman.shadow" version "${shadowJarPluginVersion}"
+        id "de.undercouch.download" version "${downloadPluginVersion}"
+        id "net.researchgate.release" version "${releasePluginVersion}"
+        id "io.ballerina.plugin" version "${ballerinaGradlePluginVersion}"
+    }
+    repositories {
+        gradlePluginPortal()
+        maven {
+            url = 'https://maven.pkg.github.com/ballerina-platform/*'
+            credentials {
+                username System.getenv("packageUser")
+                password System.getenv("packagePAT")
+            }
+        }
+    }
+}
+
 plugins {
     id "com.gradle.enterprise" version "3.2"
 }