//
// Copyright 2024 Formata, Inc. All rights reserved.
//
// Licensed 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 the JSON file using the JSON format
// The explicit format is optional here, since the file extension is 'json'
import '../../json/tests/example.json' as self.example;
// Import the JSON file using the STOF format
// STOF is reverse compatable with JSON - valid JSON is always valid STOF
import stof 'src/json/tests/example.json' as self.stofexample;
#[test('SGML')]
fn sort_as(): str {
let json_sort_as = self.example.glossary.GlossDiv.GlossList.GlossEntry.SortAs;
let stof_sort_as = self.stofexample.glossary.GlossDiv.GlossList.GlossEntry.SortAs;
assertEq(json_sort_as, stof_sort_as);
return json_sort_as;
}
parse: {
#[test]
fn parse_json_string() {
let json = '
{
"json": {
"string": "hello",
"number": 42,
"boolean": true,
"array": ["hello", 42, true, [false, 24], { "embedded": true }],
"child": {
"is_child": true
}
}
}';
// Parse this JSON string using the 'json' format, placing the
// newly created object in this object under the name 'parsed'
parse(json, 'json', 'self.parsed');
assertEq(typeof self.parsed, 'obj');
assertEq(self.parsed.json.string, 'hello');
assertEq(self.parsed.json.number, 42);
assertEq(self.parsed.json.boolean, true);
assertEq(self.parsed.json.child.is_child, true);
let embedded = self.parsed.json.array.at(4);
assertEq(embedded.embedded, true);
// Now get rid of our parsed object
drop self.parsed;
assertEq(self.parsed, null);
assertEq(self.parsed.json, null);
}
#[test]
fn parse_json_with_stof() {
let json = '
{
"json": {
"string": "hello",
"number": 42,
"boolean": true,
"array": ["hello", 42, true, [false, 24], { "embedded": true }],
"child": {
"is_child": true
}
}
}';
// Parse this JSON string using the 'stof' format, placing the
// newly created object in this object under the name 'parsed_stof'
// Valid JSON is always valid STOF
parse(json, 'stof', 'self.parsed_stof');
assertEq(typeof self.parsed_stof, 'obj');
assertEq(self.parsed_stof.json.string, 'hello');
assertEq(self.parsed_stof.json.number, 42);
assertEq(self.parsed_stof.json.boolean, true);
assertEq(self.parsed_stof.json.child.is_child, true);
let embedded = self.parsed_stof.json.array.at(4);
assertEq(embedded.embedded, true);
// Now get rid of our parsed object
drop self.parsed_stof;
assertEq(self.parsed_stof, null);
assertEq(self.parsed_stof.json, null);
}
#[test]
fn parse_json_with_stof_add_types() {
let json = "
{
obj 'json': {
/**
* Type info (optional).
* Will perform casts though when parsing.
*/
str string: +100,
int number: +42; // Allow comments everywhere
bool 'boolean': true; // Don't require line endings ',' or ';' accepted
vec array: ['hello', 42, true, [false, 24,], { 'embedded': true; }] // trailing ',' in array
obj child: {
bool 'is_child': true,
}, // trailing comma in objects
}
}";
// Parse this JSON string using the 'stof' format, placing the
// newly created object in this object under the name 'parsed_types'
// Valid JSON is always valid STOF
parse(json, 'stof', 'self.parsed_types');
assertEq(typeof self.parsed_types, 'obj');
assertEq(self.parsed_types.json.string, '100');
assertEq(self.parsed_types.json.number, 42);
assertEq(self.parsed_types.json.boolean, true);
assertEq(self.parsed_types.json.child.is_child, true);
let embedded = self.parsed_types.json.array.at(4);
assertEq(embedded.embedded, true);
// Now get rid of our parsed object
drop self.parsed_types;
assertEq(self.parsed_types, null);
assertEq(self.parsed_types.json, null);
}
}
bytes: {
test_json: {
cool_factor: 100
test: 'hello'
}
#[test]
fn export_bytes() {
let bytes = blobify(self.test_json, 'json'); // Will export a utf8 blob of JSON
let json = bytes as str; // default cast from blob to str is utf8
// Now parse the bytes into ourselves as the object 'tmpjson'
// This is effectively copying 'test_json' above, placing it in parallel as 'tmpjson'
parse(bytes, 'json', 'self.tmpjson');
let parsed_json = stringify(self.tmpjson, 'json'); // turned back into a string
// Now drop our temp object now that we have a string - deletes our copy from the doc
drop self.tmpjson;
assertEq(self.tmpjson, null);
assertEq(parsed_json, json);
assertEq(json, '{"cool_factor":100,"test":"hello"}');
}
}
#[test]
fn import_nd_json() {
let ndjson = '{"first": true}\n{"second": true}\n{"third": true}';
parse(ndjson, 'ndjson', 'self.ndjson.import');
assertEq(self.ndjson.import.first, true);
assertEq(self.ndjson.import.second, true);
assertEq(self.ndjson.import.third, true);
}