-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Correct best practices, add test for JSON output using -j/-json flags
- Loading branch information
1 parent
d2bc412
commit ae2f7f5
Showing
4 changed files
with
196 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,112 +1,117 @@ | ||
#include <sourcemeta/jsontoolkit/json.h> | ||
#include <sourcemeta/jsontoolkit/jsonschema.h> | ||
|
||
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE | ||
#include <iostream> // std::cout | ||
#include <sstream> // std::ostringstream | ||
|
||
#include "command.h" | ||
#include "utils.h" | ||
|
||
const char* enumToString(sourcemeta::jsontoolkit::ReferenceEntryType type) { | ||
switch(type) { | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Resource: return "Resource"; | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Anchor: return "Anchor"; | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Pointer: return "Pointer"; | ||
default: return "Unknown"; | ||
} | ||
static auto enum_to_string(const sourcemeta::jsontoolkit::ReferenceEntryType type) -> std::string { | ||
switch (type) { | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Resource: | ||
return "Resource"; | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Anchor: | ||
return "Anchor"; | ||
case sourcemeta::jsontoolkit::ReferenceEntryType::Pointer: | ||
return "Pointer"; | ||
default: | ||
return "Unknown"; | ||
} | ||
} | ||
|
||
auto intelligence::jsonschema::cli::frame(const std::span<const std::string> &arguments) -> int { | ||
const auto options{parse_options(arguments, {"json", "j"})}; | ||
CLI_ENSURE(!options.at("").empty(), "You must pass a JSON Schema as input") | ||
const sourcemeta::jsontoolkit::JSON schema{ | ||
sourcemeta::jsontoolkit::from_file(options.at("").front()) | ||
}; | ||
const auto options{parse_options(arguments, {"json", "j"})}; | ||
CLI_ENSURE(!options.at("").empty(), "You must pass a JSON Schema as input") | ||
const sourcemeta::jsontoolkit::JSON schema{ | ||
sourcemeta::jsontoolkit::from_file(options.at("").front())}; | ||
|
||
sourcemeta::jsontoolkit::ReferenceFrame frame; | ||
sourcemeta::jsontoolkit::ReferenceMap references; | ||
sourcemeta::jsontoolkit::frame(schema, frame, references, | ||
sourcemeta::jsontoolkit::default_schema_walker, | ||
resolver(options)) | ||
.wait(); | ||
sourcemeta::jsontoolkit::ReferenceFrame frame; | ||
sourcemeta::jsontoolkit::ReferenceMap references; | ||
sourcemeta::jsontoolkit::frame(schema, frame, references, | ||
sourcemeta::jsontoolkit::default_schema_walker, | ||
resolver(options)) | ||
.wait(); | ||
|
||
bool outputJson = options.contains("json") || options.contains("j"); | ||
if (outputJson) { | ||
sourcemeta::jsontoolkit::JSON outputJson = sourcemeta::jsontoolkit::JSON::make_object(); | ||
auto frameJson = sourcemeta::jsontoolkit::JSON::make_object(); | ||
auto referencesJson = sourcemeta::jsontoolkit::JSON::make_object(); | ||
const auto output_json = options.contains("json") || options.contains("j"); | ||
if (output_json) { | ||
auto output_json_object = sourcemeta::jsontoolkit::JSON::make_object(); | ||
auto frame_json = sourcemeta::jsontoolkit::JSON::make_object(); | ||
auto references_json = sourcemeta::jsontoolkit::JSON::make_object(); | ||
|
||
for (const auto &[key, entry] : frame) { | ||
sourcemeta::jsontoolkit::JSON frameEntry = sourcemeta::jsontoolkit::JSON::make_object(); | ||
frameEntry.assign("schema", sourcemeta::jsontoolkit::JSON{entry.root.value_or("<ANONYMOUS>")}); | ||
std::ostringstream pointer_stream; | ||
sourcemeta::jsontoolkit::stringify(entry.pointer, pointer_stream); | ||
frameEntry.assign("pointer", sourcemeta::jsontoolkit::JSON{pointer_stream.str()}); | ||
frameEntry.assign("baseURI", sourcemeta::jsontoolkit::JSON{entry.base}); | ||
frameEntry.assign("type", sourcemeta::jsontoolkit::JSON{enumToString(entry.type)}); | ||
std::ostringstream reference_stream; | ||
sourcemeta::jsontoolkit::stringify(entry.relative_pointer, reference_stream); | ||
frameEntry.assign("relativePointer", sourcemeta::jsontoolkit::JSON{reference_stream.str()}); | ||
frameEntry.assign("dialect", sourcemeta::jsontoolkit::JSON{entry.dialect}); | ||
frameJson.assign(key.second, sourcemeta::jsontoolkit::JSON{frameEntry}); | ||
} | ||
outputJson.assign("frames", sourcemeta::jsontoolkit::JSON{frameJson}); | ||
for (const auto &[key, entry] : frame) { | ||
auto frame_entry = sourcemeta::jsontoolkit::JSON::make_object(); | ||
frame_entry.assign("schema", sourcemeta::jsontoolkit::JSON{entry.root.value_or("<ANONYMOUS>")}); | ||
std::ostringstream pointer_stream; | ||
sourcemeta::jsontoolkit::stringify(entry.pointer, pointer_stream); | ||
frame_entry.assign("pointer", sourcemeta::jsontoolkit::JSON{pointer_stream.str()}); | ||
frame_entry.assign("baseURI", sourcemeta::jsontoolkit::JSON{entry.base}); | ||
frame_entry.assign("type", sourcemeta::jsontoolkit::JSON{enum_to_string(entry.type)}); | ||
std::ostringstream reference_stream; | ||
sourcemeta::jsontoolkit::stringify(entry.relative_pointer, reference_stream); | ||
frame_entry.assign("relativePointer", sourcemeta::jsontoolkit::JSON{reference_stream.str()}); | ||
frame_entry.assign("dialect", sourcemeta::jsontoolkit::JSON{entry.dialect}); | ||
frame_json.assign(key.second, sourcemeta::jsontoolkit::JSON{frame_entry}); | ||
} | ||
output_json_object.assign("frames", sourcemeta::jsontoolkit::JSON{frame_json}); | ||
|
||
for (const auto &[pointer, entry] : references) { | ||
auto refEntry = sourcemeta::jsontoolkit::JSON::make_object(); | ||
refEntry.assign("type", sourcemeta::jsontoolkit::JSON{pointer.first == sourcemeta::jsontoolkit::ReferenceType::Dynamic ? "Dynamic" : "Static"}); | ||
refEntry.assign("destination", sourcemeta::jsontoolkit::JSON{entry.destination}); | ||
if (entry.base.has_value()) { | ||
refEntry.assign("fragmentBaseURI", sourcemeta::jsontoolkit::JSON{entry.base.value()}); | ||
} | ||
if (entry.fragment.has_value()) { | ||
refEntry.assign("fragment", sourcemeta::jsontoolkit::JSON{entry.fragment.value()}); | ||
} | ||
std::ostringstream ref_entry_stream; | ||
sourcemeta::jsontoolkit::stringify(pointer.second, ref_entry_stream); | ||
referencesJson.assign(ref_entry_stream.str(), sourcemeta::jsontoolkit::JSON{refEntry}); | ||
} | ||
outputJson.assign("references", sourcemeta::jsontoolkit::JSON{referencesJson}); | ||
|
||
std::ostringstream print_stream; | ||
sourcemeta::jsontoolkit::prettify(outputJson, print_stream); | ||
std::cout << print_stream.str() << std::endl; | ||
} else { | ||
for (const auto &[key, entry] : frame) { | ||
std::cout << "(LOCATION) URI: " << key.second << "\n"; | ||
std::cout << " Schema : " << entry.root.value_or("<ANONYMOUS>") << "\n"; | ||
std::cout << " Pointer :"; | ||
if (!entry.pointer.empty()) { | ||
std::cout << " "; | ||
} | ||
std::cout<<"\n"; | ||
sourcemeta::jsontoolkit::stringify(entry.pointer, std::cout); | ||
std::cout << " Base URI : " << entry.base << "\n"; | ||
std::cout << " Relative Pointer :"; | ||
if (!entry.relative_pointer.empty()) { | ||
std::cout << " "; | ||
} | ||
sourcemeta::jsontoolkit::stringify(entry.relative_pointer, std::cout); | ||
std::cout << "\n"; | ||
std::cout << " Dialect : " << entry.dialect << "\n"; | ||
} | ||
for (const auto &[pointer, entry] : references) { | ||
auto ref_entry = sourcemeta::jsontoolkit::JSON::make_object(); | ||
ref_entry.assign("type", | ||
sourcemeta::jsontoolkit::JSON{pointer.first == sourcemeta::jsontoolkit::ReferenceType::Dynamic ? "Dynamic" : "Static"}); | ||
ref_entry.assign("destination", sourcemeta::jsontoolkit::JSON{entry.destination}); | ||
if (entry.base.has_value()) { | ||
ref_entry.assign("fragmentBaseURI", sourcemeta::jsontoolkit::JSON{entry.base.value()}); | ||
} | ||
if (entry.fragment.has_value()) { | ||
ref_entry.assign("fragment", sourcemeta::jsontoolkit::JSON{entry.fragment.value()}); | ||
} | ||
std::ostringstream ref_entry_stream; | ||
sourcemeta::jsontoolkit::stringify(pointer.second, ref_entry_stream); | ||
references_json.assign(ref_entry_stream.str(), sourcemeta::jsontoolkit::JSON{ref_entry}); | ||
} | ||
output_json_object.assign("references", sourcemeta::jsontoolkit::JSON{references_json}); | ||
|
||
for (const auto &[pointer, entry] : references) { | ||
std::cout << "(REFERENCE) URI: "; | ||
sourcemeta::jsontoolkit::stringify(pointer.second, std::cout); | ||
std::cout << "\n"; | ||
std::cout << " Type : " << (pointer.first == sourcemeta::jsontoolkit::ReferenceType::Dynamic ? "Dynamic" : "Static") << "\n"; | ||
std::cout << " Destination : " << entry.destination << "\n"; | ||
std::ostringstream print_stream; | ||
sourcemeta::jsontoolkit::prettify(output_json_object, print_stream); | ||
std::cout << print_stream.str() << std::endl; | ||
} else { | ||
for (const auto &[key, entry] : frame) { | ||
std::cout << "(LOCATION) URI: " << key.second << "\n"; | ||
std::cout << " Schema : " << entry.root.value_or("<ANONYMOUS>") << "\n"; | ||
std::cout << " Pointer :"; | ||
if (!entry.pointer.empty()) { | ||
std::cout << " "; | ||
} | ||
sourcemeta::jsontoolkit::stringify(entry.pointer, std::cout); | ||
std::cout << "\n"; | ||
std::cout << " Base URI : " << entry.base << "\n"; | ||
std::cout << " Relative Pointer :"; | ||
if (!entry.relative_pointer.empty()) { | ||
std::cout << " "; | ||
} | ||
sourcemeta::jsontoolkit::stringify(entry.relative_pointer, std::cout); | ||
std::cout << "\n"; | ||
std::cout << " Dialect : " << entry.dialect << "\n"; | ||
} | ||
|
||
for (const auto &[pointer, entry] : references) { | ||
std::cout << "(REFERENCE) URI: "; | ||
sourcemeta::jsontoolkit::stringify(pointer.second, std::cout); | ||
std::cout << "\n"; | ||
std::cout << " Type : " << (pointer.first == sourcemeta::jsontoolkit::ReferenceType::Dynamic ? "Dynamic" : "Static") << "\n"; | ||
std::cout << " Destination : " << entry.destination << "\n"; | ||
|
||
if (entry.base.has_value()) { | ||
std::cout << " - (w/o fragment) : " << entry.base.value() << "\n"; | ||
} | ||
if (entry.base.has_value()) { | ||
std::cout << " - (w/o fragment) : " << entry.base.value() << "\n"; | ||
} | ||
|
||
if (entry.fragment.has_value()) { | ||
std::cout << " - (fragment) : " << entry.fragment.value() << "\n"; | ||
} | ||
} | ||
if (entry.fragment.has_value()) { | ||
std::cout << " - (fragment) : " << entry.fragment.value() << "\n"; | ||
} | ||
} | ||
} | ||
|
||
return EXIT_SUCCESS; | ||
} | ||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#!/bin/sh | ||
|
||
set -o errexit | ||
set -o nounset | ||
|
||
TMP="$(mktemp -d)" | ||
clean() { rm -rf "$TMP"; } | ||
trap clean EXIT | ||
|
||
cat << 'EOF' > "$TMP/schema.json" | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"$id": "https://example.com", | ||
"$ref": "#/$defs/string", | ||
"$defs": { | ||
"string": { "type": "string" } | ||
} | ||
} | ||
EOF | ||
|
||
# Test with --json flag | ||
"$1" frame "$TMP/schema.json" --json > "$TMP/result_json.txt" | ||
|
||
# Test with -j flag | ||
"$1" frame "$TMP/schema.json" -j > "$TMP/result.json" | ||
|
||
cat << 'EOF' > "$TMP/expected_json.txt" | ||
{ | ||
"frames": { | ||
"https://example.com": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "", | ||
"relativePointer": "", | ||
"schema": "https://example.com", | ||
"type": "Resource" | ||
}, | ||
"https://example.com#/$defs": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$defs", | ||
"relativePointer": "/$defs", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
}, | ||
"https://example.com#/$defs/string": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$defs/string", | ||
"relativePointer": "/$defs/string", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
}, | ||
"https://example.com#/$defs/string/type": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$defs/string/type", | ||
"relativePointer": "/$defs/string/type", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
}, | ||
"https://example.com#/$id": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$id", | ||
"relativePointer": "/$id", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
}, | ||
"https://example.com#/$ref": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$ref", | ||
"relativePointer": "/$ref", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
}, | ||
"https://example.com#/$schema": { | ||
"baseURI": "https://example.com", | ||
"dialect": "https://json-schema.org/draft/2020-12/schema", | ||
"pointer": "/$schema", | ||
"relativePointer": "/$schema", | ||
"schema": "https://example.com", | ||
"type": "Pointer" | ||
} | ||
}, | ||
"references": { | ||
"/$ref": { | ||
"destination": "https://example.com#/$defs/string", | ||
"fragment": "/$defs/string", | ||
"fragmentBaseURI": "https://example.com", | ||
"type": "Static" | ||
} | ||
} | ||
} | ||
EOF | ||
|
||
diff "$TMP/result_json.txt" "$TMP/expected_json.txt" |