@@ -32,67 +32,61 @@ auto find_anchors(const sourcemeta::core::JSON &schema,
3232 if (schema.is_object () &&
3333 vocabularies.contains (
3434 sourcemeta::core::Vocabularies::Known::JSON_Schema_2020_12_Core)) {
35- if (schema.defines (" $dynamicAnchor" )) {
36- const auto &anchor{schema.at (" $dynamicAnchor" )};
37- if (anchor.is_string ()) {
38- result.emplace_back (anchor.to_string (), AnchorType::Dynamic);
39- }
35+ const auto *dynamic_anchor{schema.try_at (" $dynamicAnchor" )};
36+ if (dynamic_anchor && dynamic_anchor->is_string ()) {
37+ result.emplace_back (dynamic_anchor->to_string (), AnchorType::Dynamic);
4038 }
4139
42- if (schema.defines (" $anchor" )) {
43- const auto &anchor{schema.at (" $anchor" )};
44- if (anchor.is_string ()) {
45- const std::string_view anchor_view{anchor.to_string ()};
46- bool found = false ;
47- for (auto &entry : result) {
48- if (entry.first == anchor_view) {
49- entry.second = AnchorType::All;
50- found = true ;
51- break ;
52- }
53- }
54- if (!found) {
55- result.emplace_back (anchor_view, AnchorType::Static);
40+ const auto *anchor_2020{schema.try_at (" $anchor" )};
41+ if (anchor_2020 && anchor_2020->is_string ()) {
42+ const std::string_view anchor_view{anchor_2020->to_string ()};
43+ bool found = false ;
44+ for (auto &entry : result) {
45+ if (entry.first == anchor_view) {
46+ entry.second = AnchorType::All;
47+ found = true ;
48+ break ;
5649 }
5750 }
51+ if (!found) {
52+ result.emplace_back (anchor_view, AnchorType::Static);
53+ }
5854 }
5955 }
6056
6157 // 2019-09
6258 if (schema.is_object () &&
6359 vocabularies.contains (
6460 sourcemeta::core::Vocabularies::Known::JSON_Schema_2019_09_Core)) {
65- if ( schema.defines (" $recursiveAnchor" )) {
66- const auto &anchor{schema. at ( " $recursiveAnchor " )};
67- if (anchor. is_boolean ()) {
68- if (anchor. to_boolean ()) {
61+ const auto *recursive_anchor{ schema.try_at (" $recursiveAnchor" )};
62+ if (recursive_anchor) {
63+ if (recursive_anchor-> is_boolean ()) {
64+ if (recursive_anchor-> to_boolean ()) {
6965 // We store a 2019-09 recursive anchor as an empty anchor
7066 result.emplace_back (std::string_view{}, AnchorType::Dynamic);
7167 }
7268 } else {
7369 std::ostringstream value;
74- sourcemeta::core::stringify (anchor , value);
70+ sourcemeta::core::stringify (*recursive_anchor , value);
7571 throw sourcemeta::core::SchemaKeywordError (
7672 " $recursiveAnchor" , value.str (), " Invalid recursive anchor value" );
7773 }
7874 }
7975
80- if (schema.defines (" $anchor" )) {
81- const auto &anchor{schema.at (" $anchor" )};
82- if (anchor.is_string ()) {
83- const std::string_view anchor_view{anchor.to_string ()};
84- bool found = false ;
85- for (auto &entry : result) {
86- if (entry.first == anchor_view) {
87- entry.second = AnchorType::All;
88- found = true ;
89- break ;
90- }
91- }
92- if (!found) {
93- result.emplace_back (anchor_view, AnchorType::Static);
76+ const auto *anchor_2019{schema.try_at (" $anchor" )};
77+ if (anchor_2019 && anchor_2019->is_string ()) {
78+ const std::string_view anchor_view{anchor_2019->to_string ()};
79+ bool found = false ;
80+ for (auto &entry : result) {
81+ if (entry.first == anchor_view) {
82+ entry.second = AnchorType::All;
83+ found = true ;
84+ break ;
9485 }
9586 }
87+ if (!found) {
88+ result.emplace_back (anchor_view, AnchorType::Static);
89+ }
9690 }
9791 }
9892
@@ -103,9 +97,10 @@ auto find_anchors(const sourcemeta::core::JSON &schema,
10397 sourcemeta::core::Vocabularies::Known::JSON_Schema_Draft_7) ||
10498 vocabularies.contains (
10599 sourcemeta::core::Vocabularies::Known::JSON_Schema_Draft_6))) {
106- if (schema.defines (" $id" )) {
107- assert (schema.at (" $id" ).is_string ());
108- const std::string_view id_view{schema.at (" $id" ).to_string ()};
100+ const auto *id_value{schema.try_at (" $id" )};
101+ if (id_value) {
102+ assert (id_value->is_string ());
103+ const std::string_view id_view{id_value->to_string ()};
109104 if (id_view.starts_with (' #' )) {
110105 // The original string is "#fragment", skip the '#'
111106 result.emplace_back (id_view.substr (1 ), AnchorType::Static);
@@ -118,9 +113,10 @@ auto find_anchors(const sourcemeta::core::JSON &schema,
118113 if (schema.is_object () &&
119114 vocabularies.contains (
120115 sourcemeta::core::Vocabularies::Known::JSON_Schema_Draft_4)) {
121- if (schema.defines (" id" )) {
122- assert (schema.at (" id" ).is_string ());
123- const std::string_view id_view{schema.at (" id" ).to_string ()};
116+ const auto *id_value{schema.try_at (" id" )};
117+ if (id_value) {
118+ assert (id_value->is_string ());
119+ const std::string_view id_view{id_value->to_string ()};
124120 if (id_view.starts_with (' #' )) {
125121 // The original string is "#fragment", skip the '#'
126122 result.emplace_back (id_view.substr (1 ), AnchorType::Static);
@@ -900,17 +896,16 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
900896 base_uris, common_pointer_weak,
901897 entry.id ? std::optional<std::string_view>{*entry.id }
902898 : std::nullopt )};
903- if (entry.common .subschema .get ().defines (" $ref" )) {
904- if (!entry.common .subschema .get ().at (" $ref" ).is_string ()) {
899+ const auto *ref_value{entry.common .subschema .get ().try_at (" $ref" )};
900+ if (ref_value) {
901+ if (!ref_value->is_string ()) {
905902 std::ostringstream value;
906- sourcemeta::core::stringify (entry.common .subschema .get ().at (" $ref" ),
907- value);
903+ sourcemeta::core::stringify (*ref_value, value);
908904 throw sourcemeta::core::SchemaKeywordError (" $ref" , value.str (),
909905 " Invalid reference value" );
910906 }
911907
912- const auto &original{
913- entry.common .subschema .get ().at (" $ref" ).to_string ()};
908+ const auto &original{ref_value->to_string ()};
914909 sourcemeta::core::URI ref;
915910 try {
916911 ref = sourcemeta::core::URI{original};
@@ -935,20 +930,21 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
935930 set_base_and_fragment (it->second );
936931 }
937932
938- if (entry.common .vocabularies .contains (
939- Vocabularies::Known::JSON_Schema_2019_09_Core) &&
940- entry.common .subschema .get ().defines (" $recursiveRef" )) {
941- if (!entry.common .subschema .get ().at (" $recursiveRef" ).is_string ()) {
933+ const auto *recursive_ref_value{
934+ entry.common .vocabularies .contains (
935+ Vocabularies::Known::JSON_Schema_2019_09_Core)
936+ ? entry.common .subschema .get ().try_at (" $recursiveRef" )
937+ : nullptr };
938+ if (recursive_ref_value) {
939+ if (!recursive_ref_value->is_string ()) {
942940 std::ostringstream value;
943- sourcemeta::core::stringify (
944- entry.common .subschema .get ().at (" $recursiveRef" ), value);
941+ sourcemeta::core::stringify (*recursive_ref_value, value);
945942 throw sourcemeta::core::SchemaKeywordError (
946943 " $recursiveRef" , value.str (),
947944 " Invalid recursive reference value" );
948945 }
949946
950- const auto &ref{
951- entry.common .subschema .get ().at (" $recursiveRef" ).to_string ()};
947+ const auto &ref{recursive_ref_value->to_string ()};
952948
953949 // The behavior of this keyword is defined only for the value "#".
954950 // Implementations MAY choose to consider other values to be errors.
@@ -980,19 +976,20 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
980976 set_base_and_fragment (it->second );
981977 }
982978
983- if (entry.common .vocabularies .contains (
984- Vocabularies::Known::JSON_Schema_2020_12_Core) &&
985- entry.common .subschema .get ().defines (" $dynamicRef" )) {
986- if (!entry.common .subschema .get ().at (" $dynamicRef" ).is_string ()) {
979+ const auto *dynamic_ref_value{
980+ entry.common .vocabularies .contains (
981+ Vocabularies::Known::JSON_Schema_2020_12_Core)
982+ ? entry.common .subschema .get ().try_at (" $dynamicRef" )
983+ : nullptr };
984+ if (dynamic_ref_value) {
985+ if (!dynamic_ref_value->is_string ()) {
987986 std::ostringstream value;
988- sourcemeta::core::stringify (
989- entry.common .subschema .get ().at (" $dynamicRef" ), value);
987+ sourcemeta::core::stringify (*dynamic_ref_value, value);
990988 throw sourcemeta::core::SchemaKeywordError (
991989 " $dynamicRef" , value.str (), " Invalid dynamic reference value" );
992990 }
993991
994- const auto &original{
995- entry.common .subschema .get ().at (" $dynamicRef" ).to_string ()};
992+ const auto &original{dynamic_ref_value->to_string ()};
996993 sourcemeta::core::URI ref;
997994 try {
998995 ref = sourcemeta::core::URI{original};
0 commit comments