Skip to content

Commit

Permalink
Correct the type Options
Browse files Browse the repository at this point in the history
  • Loading branch information
prakanth97 committed Apr 2, 2024
1 parent 18a8490 commit 9ec1cbc
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 31 deletions.
15 changes: 9 additions & 6 deletions ballerina/json_api.bal
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/jballerina.java;

# Convert value of type `json` to subtype of `anydata`.
Expand Down Expand Up @@ -56,16 +55,20 @@ public isolated function parseStream(stream<byte[], error?> s, Options options =
#
# + v - Source anydata value
# + return - representation of `v` as value of type json
public isolated function toJson(anydata v)
public isolated function toJson(anydata v)
returns json|Error = @java:Method {'class: "io.ballerina.lib.data.jsondata.json.Native"} external;

# Represent the options that can be used to modify the behaviour of the projection.
#
# + allowDataProjection - enable or disable projection
# + allowDataProjection - Enable or disable projection.
public type Options record {
boolean nilAsOptionalField = false;
boolean absentAsNilableType = false;
}|false;
record {
# If true, nil values will be considered as optional fields in the projection.
boolean nilAsOptionalField = false;
# If true, absent fields will be considered as nilable types in the projection.
boolean absentAsNilableType = false;
}|false allowDataProjection = {};
};

# Represents the error type of the ballerina/data.jsondata module. This error type represents any error that can occur
# during the execution of jsondata APIs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import ballerina/test;

const options = false;
const options = {allowDataProjection: false};

@test:Config
isolated function testDisableDataProjectionInArrayTypeForParseString() {
Expand Down
37 changes: 30 additions & 7 deletions ballerina/tests/from_json_with_projection_options_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,38 @@
// under the License.

import ballerina/io;
import ballerina/test;
import ballerina/lang.value;
import ballerina/test;

const PATH = "tests/resources/";

const options1 = {nilAsOptionalField: true, absentAsNilableType: false};
const options2 = {nilAsOptionalField: false, absentAsNilableType: true};
const options3 = {nilAsOptionalField: true, absentAsNilableType: true};
const options4 = {nilAsOptionalField: false, absentAsNilableType: false};
const options1 = {
allowDataProjection: {
nilAsOptionalField: true,
absentAsNilableType: false
}
};

const options2 = {
allowDataProjection: {
nilAsOptionalField: false,
absentAsNilableType: true
}
};

const options3 = {
allowDataProjection: {
nilAsOptionalField: true,
absentAsNilableType: true
}
};

const options4 = {
allowDataProjection: {
nilAsOptionalField: false,
absentAsNilableType: false
}
};

type Sales record {|
@Name {
Expand Down Expand Up @@ -251,7 +274,7 @@ type ResponseEcom record {
isolated function testAbsentAsNilableTypeAndAbsentAsNilableTypeForParseString() returns error? {
string jsonData = check io:fileReadString(PATH + "product_list_response.json");
ResponseEcom response = check parseString(jsonData, options3);

test:assertEquals(response.status, "success");
test:assertEquals(response.data.products[0].length(), 6);
test:assertEquals(response.data.products[0].id, 1);
Expand Down Expand Up @@ -313,7 +336,7 @@ isolated function testAbsentAsNilableTypeAndAbsentAsNilableTypeForParseString2()
string jsonData = check io:fileReadString(PATH + "product_list_response.json");
json productJson = check value:fromJsonString(jsonData);
ResponseEcom response = check parseAsType(productJson, options3);

test:assertEquals(response.status, "success");
test:assertEquals(response.data.products[0].length(), 6);
test:assertEquals(response.data.products[0].id, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import io.ballerina.runtime.api.types.MethodType;
import io.ballerina.runtime.api.types.ObjectType;
import io.ballerina.runtime.api.utils.TypeUtils;
import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BObject;
import io.ballerina.runtime.api.values.BString;
import io.ballerina.runtime.api.values.BTypedesc;

import java.io.InputStreamReader;
Expand All @@ -44,9 +46,10 @@ public class DataReaderTask implements Runnable {
private final BObject iteratorObj;
private final Future future;
private final BTypedesc typed;
private final Object options;
private final BMap<BString, Object> options;

public DataReaderTask(Environment env, BObject iteratorObj, Future future, BTypedesc typed, Object options) {
public DataReaderTask(Environment env, BObject iteratorObj, Future future, BTypedesc typed,
BMap<BString, Object> options) {
this.env = env;
this.iteratorObj = iteratorObj;
this.future = future;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class JsonParser {
* @return JSON structure
* @throws BError for any parsing error
*/
public static Object parse(Reader reader, Object options, Type type)
public static Object parse(Reader reader, BMap<BString, Object> options, Type type)
throws BError {
StateMachine sm = tlStateMachine.get();
try {
Expand Down Expand Up @@ -197,9 +197,8 @@ private void processLocation(char ch) {
}
}

public Object execute(Reader reader, Object options, Type type) throws BError {
public Object execute(Reader reader, BMap<BString, Object> options, Type type) throws BError {
switch (type.getTag()) {
// TODO: Handle readonly and singleton type as expType.
case TypeTags.RECORD_TYPE_TAG -> {
RecordType recordType = (RecordType) type;
expectedTypes.push(recordType);
Expand Down Expand Up @@ -249,10 +248,15 @@ public Object execute(Reader reader, Object options, Type type) throws BError {
default -> throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE, type);
}

if (options instanceof BMap<?, ?>) {
allowDataProjection = true;
absentAsNilableType = (Boolean) ((BMap<?, ?>) options).get(Constants.ABSENT_AS_NILABLE_TYPE);
nilAsOptionalField = (Boolean) ((BMap<?, ?>) options).get(Constants.NIL_AS_OPTIONAL_FIELD);
Object allowDataProjection = options.get(Constants.ALLOW_DATA_PROJECTION);
if (allowDataProjection instanceof Boolean) {
this.allowDataProjection = false;
} else if (allowDataProjection instanceof BMap<?, ?>) {
this.allowDataProjection = true;
this.absentAsNilableType =
(Boolean) ((BMap<?, ?>) allowDataProjection).get(Constants.ABSENT_AS_NILABLE_TYPE);
this.nilAsOptionalField =
(Boolean) ((BMap<?, ?>) allowDataProjection).get(Constants.NIL_AS_OPTIONAL_FIELD);
}

State currentState = DOC_START_STATE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,18 @@ public class JsonTraverse {

private static final ThreadLocal<JsonTree> tlJsonTree = ThreadLocal.withInitial(JsonTree::new);

public static Object traverse(Object json, Object options, Type type) {
public static Object traverse(Object json, BMap<BString, Object> options, Type type) {
JsonTree jsonTree = tlJsonTree.get();
try {
if (options instanceof BMap) {
Object allowDataProjection = options.get(Constants.ALLOW_DATA_PROJECTION);
if (allowDataProjection instanceof Boolean) {
jsonTree.allowDataProjection = false;
} else if (allowDataProjection instanceof BMap<?, ?>) {
jsonTree.allowDataProjection = true;
jsonTree.absentAsNilableType = (Boolean) ((BMap<?, ?>) options).get(Constants.ABSENT_AS_NILABLE_TYPE);
jsonTree.nilAsOptionalField = (Boolean) ((BMap<?, ?>) options).get(Constants.NIL_AS_OPTIONAL_FIELD);
jsonTree.absentAsNilableType =
(Boolean) ((BMap<?, ?>) allowDataProjection).get(Constants.ABSENT_AS_NILABLE_TYPE);
jsonTree.nilAsOptionalField =
(Boolean) ((BMap<?, ?>) allowDataProjection).get(Constants.NIL_AS_OPTIONAL_FIELD);
}
return jsonTree.traverseJson(json, type);
} catch (BError e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.ballerina.runtime.api.utils.JsonUtils;
import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BError;
import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BObject;
import io.ballerina.runtime.api.values.BStream;
import io.ballerina.runtime.api.values.BString;
Expand All @@ -41,23 +42,23 @@
*/
public class Native {

public static Object parseAsType(Object json, Object options, BTypedesc typed) {
public static Object parseAsType(Object json, BMap<BString, Object> options, BTypedesc typed) {
try {
return JsonTraverse.traverse(json, options, typed.getDescribingType());
} catch (BError e) {
return e;
}
}

public static Object parseString(BString json, Object options, BTypedesc typed) {
public static Object parseString(BString json, BMap<BString, Object> options, BTypedesc typed) {
try {
return JsonParser.parse(new StringReader(json.getValue()), options, typed.getDescribingType());
} catch (BError e) {
return e;
}
}

public static Object parseBytes(BArray json, Object options, BTypedesc typed) {
public static Object parseBytes(BArray json, BMap<BString, Object> options, BTypedesc typed) {
try {
byte[] bytes = json.getBytes();
return JsonParser.parse(new InputStreamReader(new ByteArrayInputStream(bytes)), options,
Expand All @@ -67,7 +68,7 @@ public static Object parseBytes(BArray json, Object options, BTypedesc typed) {
}
}

public static Object parseStream(Environment env, BStream json, Object options, BTypedesc typed) {
public static Object parseStream(Environment env, BStream json, BMap<BString, Object> options, BTypedesc typed) {
final BObject iteratorObj = json.getIteratorObj();
final Future future = env.markAsync();
DataReaderTask task = new DataReaderTask(env, iteratorObj, future, typed, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class Constants {
public static final String FIELD = "$field$.";
public static final String FIELD_REGEX = "\\$field\\$\\.";
public static final String NAME = "Name";
public static final BString ALLOW_DATA_PROJECTION = StringUtils.fromString("allowDataProjection");
public static final BString NIL_AS_OPTIONAL_FIELD = StringUtils.fromString("nilAsOptionalField");
public static final BString ABSENT_AS_NILABLE_TYPE = StringUtils.fromString("absentAsNilableType");
public static final String NULL_VALUE = "null";
Expand Down

0 comments on commit 9ec1cbc

Please sign in to comment.