lutaml-model 0.8.19 → 0.8.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-tests.yml +1 -1
- data/.github/workflows/rake.yml +1 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +133 -72
- data/bench/bench_common.rb +8 -5
- data/bench/bench_niso.rb +1 -2
- data/bench/gate_config.rb +4 -1
- data/benchmark/serialization_benchmark.rb +4 -4
- data/docs/_guides/value-transformations.adoc +27 -0
- data/docs/_guides/xml-mapping.adoc +31 -0
- data/lib/compat/opal/generate_boot.rb +3 -1
- data/lib/compat/opal/lutaml_model_boot.rb +10 -7
- data/lib/compat/opal/moxml_boot.rb +6 -1
- data/lib/lutaml/hash_format/format.rb +29 -0
- data/lib/lutaml/hash_format.rb +5 -27
- data/lib/lutaml/json/adapter/oj_adapter.rb +7 -0
- data/lib/lutaml/json/adapter/standard_adapter.rb +17 -5
- data/lib/lutaml/json/format.rb +61 -0
- data/lib/lutaml/json/generator_options.rb +62 -0
- data/lib/lutaml/json.rb +4 -59
- data/lib/lutaml/jsonl/adapter/standard_adapter.rb +1 -1
- data/lib/lutaml/jsonl/format.rb +22 -0
- data/lib/lutaml/jsonl.rb +5 -19
- data/lib/lutaml/jsonld/adapter.rb +12 -4
- data/lib/lutaml/key_value/adapter/json/oj_adapter.rb +7 -0
- data/lib/lutaml/key_value/adapter/json/standard_adapter.rb +17 -5
- data/lib/lutaml/key_value/adapter/jsonl/standard_adapter.rb +1 -1
- data/lib/lutaml/key_value/format.rb +26 -0
- data/lib/lutaml/key_value/transform.rb +4 -1
- data/lib/lutaml/key_value/transformation/value_serializer.rb +0 -2
- data/lib/lutaml/key_value.rb +4 -21
- data/lib/lutaml/model/attribute.rb +38 -4
- data/lib/lutaml/model/collection.rb +7 -2
- data/lib/lutaml/model/compiled_rule.rb +1 -1
- data/lib/lutaml/model/config.rb +2 -2
- data/lib/lutaml/model/consolidation_map.rb +2 -2
- data/lib/lutaml/model/consolidation_rule/dispatch_block.rb +2 -2
- data/lib/lutaml/model/errors.rb +2 -2
- data/lib/lutaml/model/global_context.rb +4 -2
- data/lib/lutaml/model/mapping/mapping_rule.rb +4 -1
- data/lib/lutaml/model/mapping/model_mapping.rb +2 -2
- data/lib/lutaml/model/runtime_compatibility.rb +2 -2
- data/lib/lutaml/model/schema/class_loader.rb +2 -1
- data/lib/lutaml/model/schema/decorators/definition_collection.rb +4 -4
- data/lib/lutaml/model/schema/definitions/namespace.rb +2 -1
- data/lib/lutaml/model/schema/file_writer.rb +5 -2
- data/lib/lutaml/model/schema/renderers/base.rb +4 -3
- data/lib/lutaml/model/schema/renderers/mappings.rb +9 -3
- data/lib/lutaml/model/schema/renderers/member_decls.rb +9 -3
- data/lib/lutaml/model/schema/renderers/model.rb +18 -6
- data/lib/lutaml/model/schema/renderers/required_files_calculator.rb +2 -1
- data/lib/lutaml/model/schema/renderers.rb +2 -1
- data/lib/lutaml/model/schema/rnc_compiler/source_resolver.rb +6 -2
- data/lib/lutaml/model/schema/rnc_compiler.rb +3 -1
- data/lib/lutaml/model/schema/rng_compiler/element_visitor.rb +35 -15
- data/lib/lutaml/model/schema/rng_compiler/value_type_resolver.rb +4 -2
- data/lib/lutaml/model/schema/rng_compiler.rb +10 -5
- data/lib/lutaml/model/schema/xml_compiler/element_order.rb +2 -1
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/complex_types.rb +4 -2
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/members.rb +39 -13
- data/lib/lutaml/model/schema/xml_compiler/spec_builder.rb +29 -10
- data/lib/lutaml/model/schema/xml_compiler/supported_data_types.rb +2 -2
- data/lib/lutaml/model/schema/xml_compiler.rb +10 -5
- data/lib/lutaml/model/sequence.rb +4 -4
- data/lib/lutaml/model/serialization_adapter.rb +1 -1
- data/lib/lutaml/model/serialize/attribute_definition.rb +1 -0
- data/lib/lutaml/model/serialize/format_conversion.rb +40 -9
- data/lib/lutaml/model/serialize/initialization.rb +9 -1
- data/lib/lutaml/model/serialize/model_import.rb +1 -0
- data/lib/lutaml/model/serialize.rb +22 -3
- data/lib/lutaml/model/transformation.rb +5 -0
- data/lib/lutaml/model/type/uninitialized_class_guard.rb +1 -1
- data/lib/lutaml/model/type.rb +9 -0
- data/lib/lutaml/model/type_registry.rb +2 -2
- data/lib/lutaml/model/uninitialized_class.rb +1 -1
- data/lib/lutaml/model/union.rb +5 -2
- data/lib/lutaml/model/utils.rb +2 -2
- data/lib/lutaml/model/value_policy.rb +27 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +17 -16
- data/lib/lutaml/rdf/mapping.rb +2 -2
- data/lib/lutaml/rdf/namespace_set.rb +2 -2
- data/lib/lutaml/rdf/transform.rb +2 -2
- data/lib/lutaml/toml/format.rb +48 -0
- data/lib/lutaml/toml.rb +5 -46
- data/lib/lutaml/xml/adapter/base_adapter.rb +2 -2
- data/lib/lutaml/xml/builder/base.rb +2 -2
- data/lib/lutaml/xml/format.rb +331 -0
- data/lib/lutaml/xml/mapping.rb +26 -2
- data/lib/lutaml/xml/mapping_rule.rb +62 -3
- data/lib/lutaml/xml/model_transform.rb +183 -55
- data/lib/lutaml/xml/namespace_collector.rb +3 -3
- data/lib/lutaml/xml/parse_session.rb +59 -0
- data/lib/lutaml/xml/parsed_namespace_set.rb +2 -2
- data/lib/lutaml/xml/schema/builder.rb +5 -5
- data/lib/lutaml/xml/schema/xsd/schema_location_mapping.rb +2 -2
- data/lib/lutaml/xml/schema/xsd.rb +0 -2
- data/lib/lutaml/xml/schema/xsd_schema.rb +2 -1
- data/lib/lutaml/xml/serialization/format_conversion.rb +3 -3
- data/lib/lutaml/xml/transformation/element_builder.rb +2 -1
- data/lib/lutaml/xml/transformation/ordered_applier.rb +2 -1
- data/lib/lutaml/xml/transformation.rb +29 -0
- data/lib/lutaml/xml/xml_element.rb +2 -0
- data/lib/lutaml/xml.rb +4 -328
- data/lib/lutaml/yaml/format.rb +30 -0
- data/lib/lutaml/yaml.rb +5 -28
- data/lib/lutaml/yamls/adapter/mapping.rb +2 -2
- data/lib/lutaml/yamls/format.rb +22 -0
- data/lib/lutaml/yamls.rb +5 -19
- data/lib/tasks/benchmark_runner.rb +2 -2
- data/lutaml-model.gemspec +1 -1
- data/spec/lutaml/json/adapter/standard_adapter_spec.rb +159 -0
- data/spec/lutaml/jsonld/adapter_spec.rb +19 -0
- data/spec/lutaml/model/attribute_apply_value_map_spec.rb +26 -13
- data/spec/lutaml/model/attribute_spec.rb +8 -3
- data/spec/lutaml/model/collection_spec.rb +1 -1
- data/spec/lutaml/model/collection_state_nesting_spec.rb +44 -0
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +2 -2
- data/spec/lutaml/model/custom_from_empty_values_spec.rb +74 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +8 -8
- data/spec/lutaml/model/defaults_spec.rb +45 -0
- data/spec/lutaml/model/generator_defaults_spec.rb +101 -0
- data/spec/lutaml/model/json_spec.rb +1 -2
- data/spec/lutaml/model/json_state_nesting_spec.rb +82 -0
- data/spec/lutaml/model/serialize/builder_spec.rb +6 -3
- data/spec/lutaml/model/store_spec.rb +3 -1
- data/spec/lutaml/model/transform_apply_value_map_spec.rb +6 -3
- data/spec/lutaml/model/union_attribute_spec.rb +4 -2
- data/spec/lutaml/model/value_policy_spec.rb +82 -0
- data/spec/lutaml/require_load_order_spec.rb +25 -0
- data/spec/lutaml/xml/attribute_element_namespace_disjoint_spec.rb +88 -0
- data/spec/lutaml/xml/attribute_namespace_disjointness_spec.rb +125 -0
- data/spec/lutaml/xml/out_of_namespace_parsing_spec.rb +123 -0
- data/spec/lutaml/xml/schema/rnc_compiler_spec.rb +17 -6
- data/spec/lutaml/xml/schema/rng_compiler_spec.rb +15 -6
- data/spec/lutaml/xml/shared_element_rules_spec.rb +64 -0
- data/spec/lutaml/xml/w3c_types_spec.rb +3 -6
- metadata +26 -4
|
@@ -34,6 +34,10 @@ if RUBY_ENGINE == "opal"
|
|
|
34
34
|
require "moxml/doctype"
|
|
35
35
|
require "moxml/entity_reference"
|
|
36
36
|
require "moxml/entity_registry"
|
|
37
|
+
require "moxml/entity"
|
|
38
|
+
require "moxml/entity/restorer"
|
|
39
|
+
require "moxml/entity/reference"
|
|
40
|
+
require "moxml/xml_emitter"
|
|
37
41
|
require "moxml/adapter"
|
|
38
42
|
require "moxml/adapter/base"
|
|
39
43
|
require "moxml/adapter/customized_rexml"
|
|
@@ -46,10 +50,11 @@ if RUBY_ENGINE == "opal"
|
|
|
46
50
|
require "moxml/sax/namespace_splitter"
|
|
47
51
|
require "moxml/adapter/rexml"
|
|
48
52
|
require "moxml/adapter/customized_oga"
|
|
53
|
+
require "moxml/adapter/customized_oga/entity_decoder"
|
|
54
|
+
require "moxml/adapter/customized_oga/raw_value_override"
|
|
49
55
|
require "moxml/adapter/customized_oga/xml_declaration"
|
|
50
56
|
require "moxml/adapter/customized_oga/xml_generator"
|
|
51
57
|
require "moxml/adapter/oga"
|
|
52
|
-
require "moxml/document_builder"
|
|
53
58
|
require "moxml/builder"
|
|
54
59
|
require "moxml/context"
|
|
55
60
|
require "moxml/config"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal Hash format implementation. Loaded from lib/lutaml/hash_format.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module HashFormat
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
|
17
|
+
:hash,
|
|
18
|
+
mapping_class: Lutaml::HashFormat::Adapter::Mapping,
|
|
19
|
+
adapter_class: Lutaml::HashFormat::Adapter::StandardAdapter,
|
|
20
|
+
transformer: Lutaml::HashFormat::Adapter::Transform,
|
|
21
|
+
key_value: true,
|
|
22
|
+
adapter_options: {
|
|
23
|
+
available: %i[standard standard_hash],
|
|
24
|
+
default: :standard,
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
require_relative "type/serializers"
|
|
29
|
+
Lutaml::HashFormat::Type::Serializers.register_all!
|
data/lib/lutaml/hash_format.rb
CHANGED
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Hash format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
|
|
10
|
-
autoload :Adapter, "#{__dir__}/hash_format/adapter"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Register Hash format with the format registry
|
|
15
|
-
Lutaml::Model::FormatRegistry.register(
|
|
16
|
-
:hash,
|
|
17
|
-
mapping_class: Lutaml::HashFormat::Adapter::Mapping,
|
|
18
|
-
adapter_class: Lutaml::HashFormat::Adapter::StandardAdapter,
|
|
19
|
-
transformer: Lutaml::HashFormat::Adapter::Transform,
|
|
20
|
-
key_value: true,
|
|
21
|
-
adapter_options: {
|
|
22
|
-
available: %i[standard standard_hash],
|
|
23
|
-
default: :standard,
|
|
24
|
-
},
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
# Register Hash type serializers
|
|
28
|
-
require_relative "hash_format/type/serializers"
|
|
29
|
-
Lutaml::HashFormat::Type::Serializers.register_all!
|
|
3
|
+
# Public Hash format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
6
|
+
require_relative "model"
|
|
7
|
+
require_relative "hash_format/format"
|
|
@@ -17,6 +17,13 @@ module Lutaml
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# rubocop:disable Style/ArgumentsForwarding -- anonymous * requires Ruby 3.2+
|
|
20
|
+
# Oj has its own option namespace and its own escape_mode. Handing it
|
|
21
|
+
# the stdlib generator's options overrides that configuration, so it
|
|
22
|
+
# takes none of them -- which is what it received before.
|
|
23
|
+
def ignores_generator_options?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
20
27
|
def to_json(*args)
|
|
21
28
|
require "oj"
|
|
22
29
|
# Handle KeyValueElement input (new symmetric architecture)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "../generator_options"
|
|
4
5
|
|
|
5
6
|
module Lutaml
|
|
6
7
|
module Json
|
|
@@ -9,12 +10,16 @@ module Lutaml
|
|
|
9
10
|
FORMAT_SYMBOL = :json
|
|
10
11
|
|
|
11
12
|
def self.parse(json, _options = {})
|
|
12
|
-
JSON.parse(json
|
|
13
|
+
JSON.parse(json)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
# This adapter hands its payload to the stdlib generator, so a
|
|
17
|
+
# JSON::State carrying the outer formatting is meaningful here.
|
|
18
|
+
def accepts_generator_state?
|
|
19
|
+
true
|
|
20
|
+
end
|
|
17
21
|
|
|
22
|
+
def to_json(*args)
|
|
18
23
|
# Handle KeyValueElement input (new symmetric architecture)
|
|
19
24
|
attributes_to_serialize = if @attributes.is_a?(Lutaml::KeyValue::DataModel::Element)
|
|
20
25
|
# Unwrap __root__ wrapper to get actual content
|
|
@@ -24,10 +29,17 @@ module Lutaml
|
|
|
24
29
|
@attributes
|
|
25
30
|
end
|
|
26
31
|
|
|
32
|
+
unless GeneratorOptions.lutaml_options?(args.first)
|
|
33
|
+
return JSON.generate(attributes_to_serialize, args.first)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
options = args.first || {}
|
|
37
|
+
generator_options = GeneratorOptions.filter(options)
|
|
38
|
+
|
|
27
39
|
if options[:pretty]
|
|
28
|
-
JSON.pretty_generate(attributes_to_serialize,
|
|
40
|
+
JSON.pretty_generate(attributes_to_serialize, generator_options)
|
|
29
41
|
else
|
|
30
|
-
JSON.generate(attributes_to_serialize,
|
|
42
|
+
JSON.generate(attributes_to_serialize, generator_options)
|
|
31
43
|
end
|
|
32
44
|
end
|
|
33
45
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal JSON format implementation. Loaded from lib/lutaml/json.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
require "lutaml/model/runtime_compatibility"
|
|
9
|
+
require_relative "../key_value/format"
|
|
10
|
+
|
|
11
|
+
module Lutaml
|
|
12
|
+
module Json
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
|
|
15
|
+
require_relative "adapter/document"
|
|
16
|
+
require_relative "adapter/mapping"
|
|
17
|
+
require_relative "adapter/mapping_rule"
|
|
18
|
+
require_relative "adapter/transform"
|
|
19
|
+
require_relative "adapter/standard_adapter"
|
|
20
|
+
Lutaml::Model::RuntimeCompatibility.require_native(
|
|
21
|
+
"#{__dir__}/adapter/oj_adapter",
|
|
22
|
+
"#{__dir__}/adapter/multi_json_adapter",
|
|
23
|
+
)
|
|
24
|
+
require_relative "schema"
|
|
25
|
+
|
|
26
|
+
# Convenience aliases for common classes at the module level
|
|
27
|
+
# Allows Lutaml::Json::Mapping to resolve to Lutaml::Json::Adapter::Mapping
|
|
28
|
+
def self.const_missing(name)
|
|
29
|
+
if Adapter.const_defined?(name, false)
|
|
30
|
+
Adapter.const_get(name, false)
|
|
31
|
+
else
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Detect available JSON adapters
|
|
37
|
+
def self.detect_adapter
|
|
38
|
+
return :standard if defined?(::JSON) && Lutaml::Model.opal?
|
|
39
|
+
return :oj if defined?(::Oj)
|
|
40
|
+
return :multi_json if defined?(::MultiJson)
|
|
41
|
+
return :standard if defined?(::JSON)
|
|
42
|
+
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Lutaml::Model::FormatRegistry.register(
|
|
49
|
+
:json,
|
|
50
|
+
mapping_class: Lutaml::Json::Adapter::Mapping,
|
|
51
|
+
adapter_class: Lutaml::Json::Adapter::StandardAdapter,
|
|
52
|
+
transformer: Lutaml::Json::Adapter::Transform,
|
|
53
|
+
key_value: true,
|
|
54
|
+
adapter_options: {
|
|
55
|
+
available: %i[standard standard_json multi_json oj],
|
|
56
|
+
default: :standard,
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
require_relative "type/serializers"
|
|
61
|
+
Lutaml::Json::Type::Serializers.register_all!
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Lutaml
|
|
6
|
+
module Json
|
|
7
|
+
# Filters the options LutaML threads through serialization down to the
|
|
8
|
+
# subset the JSON generator accepts.
|
|
9
|
+
#
|
|
10
|
+
# json 2.x silently ignored unknown generator options; json 3.0 raises
|
|
11
|
+
# ArgumentError on them, so LutaML's own options (:register, :pretty and
|
|
12
|
+
# any caller-supplied extras) have to be stripped before they reach
|
|
13
|
+
# JSON.generate.
|
|
14
|
+
module GeneratorOptions
|
|
15
|
+
# Options the generator accepts on both json 2.x and 3.x. Measured
|
|
16
|
+
# against 2.9.1, 2.15.2, 2.19.9, 2.20.0, 2.21.1, 2.21.2 and 3.0.0.
|
|
17
|
+
# :escape_slash is NOT here because json 3.0 removed it; on 2.x it still
|
|
18
|
+
# arrives via DERIVED_PERMITTED. :allow_duplicate_key IS here because the
|
|
19
|
+
# generator accepts it on every version while JSON::State never exposed
|
|
20
|
+
# it as an accessor, so the derived half alone would miss it.
|
|
21
|
+
BASE_PERMITTED = %i[
|
|
22
|
+
allow_duplicate_key allow_nan array_nl as_json ascii_only
|
|
23
|
+
buffer_initial_length depth indent max_nesting object_nl script_safe
|
|
24
|
+
sort_keys space space_before strict
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
# Additive, so a json release that adds an option needs no change here.
|
|
28
|
+
# Opal's JSON shim has no State class, hence the guard.
|
|
29
|
+
DERIVED_PERMITTED =
|
|
30
|
+
if defined?(::JSON::State)
|
|
31
|
+
accessors = ::JSON::State.instance_methods(false).grep(/\A[a-z_][a-z0-9_]*=\z/)
|
|
32
|
+
accessors.map { |name| name.to_s.chomp("=").to_sym }
|
|
33
|
+
else
|
|
34
|
+
[]
|
|
35
|
+
end.freeze
|
|
36
|
+
|
|
37
|
+
PERMITTED = (BASE_PERMITTED | DERIVED_PERMITTED).freeze
|
|
38
|
+
|
|
39
|
+
# json 3.0 removed :escape_slash, which was only ever an alias of
|
|
40
|
+
# :script_safe. Dropping it would silently stop escaping slashes, so it
|
|
41
|
+
# is translated instead of discarded.
|
|
42
|
+
RENAMED = { escape_slash: :script_safe }.freeze
|
|
43
|
+
|
|
44
|
+
def self.filter(options)
|
|
45
|
+
return {} unless options.is_a?(::Hash)
|
|
46
|
+
|
|
47
|
+
options.each_with_object({}) do |(key, value), kept|
|
|
48
|
+
key = RENAMED.fetch(key, key) unless PERMITTED.include?(key)
|
|
49
|
+
kept[key] = value if PERMITTED.include?(key)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Ruby's JSON generator calls #to_json with a JSON::State whenever a
|
|
54
|
+
# document is nested inside another JSON.generate call. That is the
|
|
55
|
+
# generator's own state, not a LutaML options hash, and json 3.0 removed
|
|
56
|
+
# JSON::State#[], so it must never be read like one.
|
|
57
|
+
def self.lutaml_options?(argument)
|
|
58
|
+
argument.nil? || argument.is_a?(::Hash)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/lutaml/json.rb
CHANGED
|
@@ -1,62 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# JSON format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
require "lutaml/model/runtime_compatibility"
|
|
3
|
+
# Public JSON format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
7
6
|
require_relative "model"
|
|
8
|
-
require_relative "
|
|
9
|
-
|
|
10
|
-
module Lutaml
|
|
11
|
-
module Json
|
|
12
|
-
class Error < StandardError; end
|
|
13
|
-
|
|
14
|
-
require_relative "json/adapter/document"
|
|
15
|
-
require_relative "json/adapter/mapping"
|
|
16
|
-
require_relative "json/adapter/mapping_rule"
|
|
17
|
-
require_relative "json/adapter/transform"
|
|
18
|
-
require_relative "json/adapter/standard_adapter"
|
|
19
|
-
Lutaml::Model::RuntimeCompatibility.require_native(
|
|
20
|
-
"#{__dir__}/json/adapter/oj_adapter",
|
|
21
|
-
"#{__dir__}/json/adapter/multi_json_adapter",
|
|
22
|
-
)
|
|
23
|
-
require_relative "json/schema"
|
|
24
|
-
|
|
25
|
-
# Convenience aliases for common classes at the module level
|
|
26
|
-
# Allows Lutaml::Json::Mapping to resolve to Lutaml::Json::Adapter::Mapping
|
|
27
|
-
def self.const_missing(name)
|
|
28
|
-
if Adapter.const_defined?(name, false)
|
|
29
|
-
Adapter.const_get(name, false)
|
|
30
|
-
else
|
|
31
|
-
super
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Detect available JSON adapters
|
|
36
|
-
def self.detect_adapter
|
|
37
|
-
return :standard if defined?(::JSON) && Lutaml::Model.opal?
|
|
38
|
-
return :oj if defined?(::Oj)
|
|
39
|
-
return :multi_json if defined?(::MultiJson)
|
|
40
|
-
return :standard if defined?(::JSON)
|
|
41
|
-
|
|
42
|
-
nil
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Register JSON format with the format registry
|
|
48
|
-
Lutaml::Model::FormatRegistry.register(
|
|
49
|
-
:json,
|
|
50
|
-
mapping_class: Lutaml::Json::Adapter::Mapping,
|
|
51
|
-
adapter_class: Lutaml::Json::Adapter::StandardAdapter,
|
|
52
|
-
transformer: Lutaml::Json::Adapter::Transform,
|
|
53
|
-
key_value: true,
|
|
54
|
-
adapter_options: {
|
|
55
|
-
available: %i[standard standard_json multi_json oj],
|
|
56
|
-
default: :standard,
|
|
57
|
-
},
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
# Register JSON type serializers
|
|
61
|
-
require_relative "json/type/serializers"
|
|
62
|
-
Lutaml::Json::Type::Serializers.register_all!
|
|
7
|
+
require_relative "json/format"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal JSONL format implementation. Loaded from lib/lutaml/jsonl.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module Jsonl
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
|
17
|
+
:jsonl,
|
|
18
|
+
mapping_class: Lutaml::Jsonl::Adapter::Mapping,
|
|
19
|
+
adapter_class: Lutaml::Jsonl::Adapter::StandardAdapter,
|
|
20
|
+
transformer: Lutaml::Jsonl::Adapter::Transform,
|
|
21
|
+
key_value: true,
|
|
22
|
+
)
|
data/lib/lutaml/jsonl.rb
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# JSONL format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
|
|
10
|
-
autoload :Adapter, "#{__dir__}/jsonl/adapter"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Register JSONL format with the format registry
|
|
15
|
-
Lutaml::Model::FormatRegistry.register(
|
|
16
|
-
:jsonl,
|
|
17
|
-
mapping_class: Lutaml::Jsonl::Adapter::Mapping,
|
|
18
|
-
adapter_class: Lutaml::Jsonl::Adapter::StandardAdapter,
|
|
19
|
-
transformer: Lutaml::Jsonl::Adapter::Transform,
|
|
20
|
-
key_value: true,
|
|
21
|
-
)
|
|
3
|
+
# Public JSONL format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
6
|
+
require_relative "model"
|
|
7
|
+
require_relative "jsonl/format"
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "../json/generator_options"
|
|
4
5
|
|
|
5
6
|
module Lutaml
|
|
6
7
|
module JsonLd
|
|
7
8
|
class Adapter < Lutaml::KeyValue::Document
|
|
8
9
|
def self.parse(jsonld_string, _options = {})
|
|
9
|
-
JSON.parse(jsonld_string
|
|
10
|
+
JSON.parse(jsonld_string)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def to_jsonld(*args)
|
|
13
|
-
options = args.first || {}
|
|
14
14
|
data = @attributes
|
|
15
|
+
|
|
16
|
+
unless Lutaml::Json::GeneratorOptions.lutaml_options?(args.first)
|
|
17
|
+
return JSON.generate(data, args.first)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
options = args.first || {}
|
|
21
|
+
generator_options = Lutaml::Json::GeneratorOptions.filter(options)
|
|
22
|
+
|
|
15
23
|
if options[:pretty]
|
|
16
|
-
JSON.pretty_generate(data,
|
|
24
|
+
JSON.pretty_generate(data, generator_options)
|
|
17
25
|
else
|
|
18
|
-
JSON.generate(data,
|
|
26
|
+
JSON.generate(data, generator_options)
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
end
|
|
@@ -21,6 +21,13 @@ module Lutaml
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# rubocop:disable Style/ArgumentsForwarding -- anonymous * requires Ruby 3.2+
|
|
24
|
+
# Oj has its own option namespace and its own escape_mode. Handing it
|
|
25
|
+
# the stdlib generator's options overrides that configuration, so it
|
|
26
|
+
# takes none of them -- which is what it received before.
|
|
27
|
+
def ignores_generator_options?
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
24
31
|
def to_json(*args)
|
|
25
32
|
require "oj"
|
|
26
33
|
# Handle KeyValueElement input (new symmetric architecture)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "../../../json/generator_options"
|
|
4
5
|
|
|
5
6
|
# Backward compatibility - delegates to Lutaml::Json::Adapter
|
|
6
7
|
# @deprecated Use Lutaml::Json::Adapter::StandardAdapter instead
|
|
@@ -13,12 +14,16 @@ module Lutaml
|
|
|
13
14
|
FORMAT_SYMBOL = :json
|
|
14
15
|
|
|
15
16
|
def self.parse(json, _options = {})
|
|
16
|
-
JSON.parse(json
|
|
17
|
+
JSON.parse(json)
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
# This adapter hands its payload to the stdlib generator, so a
|
|
21
|
+
# JSON::State carrying the outer formatting is meaningful here.
|
|
22
|
+
def accepts_generator_state?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
21
25
|
|
|
26
|
+
def to_json(*args)
|
|
22
27
|
# Handle KeyValueElement input (new symmetric architecture)
|
|
23
28
|
attributes_to_serialize = if @attributes.is_a?(Lutaml::KeyValue::DataModel::Element)
|
|
24
29
|
# Unwrap __root__ wrapper to get actual content
|
|
@@ -28,10 +33,17 @@ module Lutaml
|
|
|
28
33
|
@attributes
|
|
29
34
|
end
|
|
30
35
|
|
|
36
|
+
unless Lutaml::Json::GeneratorOptions.lutaml_options?(args.first)
|
|
37
|
+
return JSON.generate(attributes_to_serialize, args.first)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
options = args.first || {}
|
|
41
|
+
generator_options = Lutaml::Json::GeneratorOptions.filter(options)
|
|
42
|
+
|
|
31
43
|
if options[:pretty]
|
|
32
|
-
JSON.pretty_generate(attributes_to_serialize,
|
|
44
|
+
JSON.pretty_generate(attributes_to_serialize, generator_options)
|
|
33
45
|
else
|
|
34
|
-
JSON.generate(attributes_to_serialize,
|
|
46
|
+
JSON.generate(attributes_to_serialize, generator_options)
|
|
35
47
|
end
|
|
36
48
|
end
|
|
37
49
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal KeyValue implementation. Loaded from lib/lutaml/key_value.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module KeyValue
|
|
10
|
+
autoload :DataModel, "#{__dir__}/data_model"
|
|
11
|
+
autoload :Document, "#{__dir__}/document"
|
|
12
|
+
autoload :Mapping, "#{__dir__}/mapping"
|
|
13
|
+
autoload :MappingRule, "#{__dir__}/mapping_rule"
|
|
14
|
+
autoload :Transform, "#{__dir__}/transform"
|
|
15
|
+
autoload :Transformation, "#{__dir__}/transformation"
|
|
16
|
+
autoload :TransformationBuilder, "#{__dir__}/transformation_builder"
|
|
17
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Register KeyValue transformation builders for all key-value formats
|
|
22
|
+
%i[json yaml toml hash].each do |format|
|
|
23
|
+
Lutaml::Model::TransformationRegistry.register_builder(
|
|
24
|
+
format, Lutaml::KeyValue::TransformationBuilder
|
|
25
|
+
)
|
|
26
|
+
end
|
|
@@ -249,7 +249,10 @@ format)
|
|
|
249
249
|
value = apply_value_map(value, rule.value_map(:from, options), attr)
|
|
250
250
|
|
|
251
251
|
if rule.has_custom_method_for_deserialization?
|
|
252
|
-
|
|
252
|
+
# An empty value ("", [], {}) is a present value per the
|
|
253
|
+
# missing-values semantics and must reach the custom method;
|
|
254
|
+
# only nil (non-existent) skips it (lutaml-model#746).
|
|
255
|
+
return if value.nil?
|
|
253
256
|
|
|
254
257
|
return rule.deserialize(instance, value, attributes, model_class)
|
|
255
258
|
end
|
|
@@ -88,11 +88,9 @@ model_class: nil)
|
|
|
88
88
|
# @param rule [CompiledRule] The compiled rule
|
|
89
89
|
# @return [Boolean] true if the rule defines a nested model
|
|
90
90
|
def nested_model?(rule)
|
|
91
|
-
# rubocop:disable Style/IncludeOrExtend
|
|
92
91
|
# Use include? instead of < because < returns nil (not false) for non-subclasses
|
|
93
92
|
rule.attribute_type.is_a?(Class) &&
|
|
94
93
|
rule.attribute_type.include?(Lutaml::Model::Serialize)
|
|
95
|
-
# rubocop:enable Style/IncludeOrExtend
|
|
96
94
|
end
|
|
97
95
|
|
|
98
96
|
# Serialize a nested model to a hash representation.
|
data/lib/lutaml/key_value.rb
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
autoload :Document, "#{__dir__}/key_value/document"
|
|
7
|
-
autoload :Mapping, "#{__dir__}/key_value/mapping"
|
|
8
|
-
autoload :MappingRule, "#{__dir__}/key_value/mapping_rule"
|
|
9
|
-
autoload :Transform, "#{__dir__}/key_value/transform"
|
|
10
|
-
autoload :Transformation, "#{__dir__}/key_value/transformation"
|
|
11
|
-
autoload :TransformationBuilder,
|
|
12
|
-
"#{__dir__}/key_value/transformation_builder"
|
|
13
|
-
autoload :Adapter, "#{__dir__}/key_value/adapter"
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
3
|
+
# Public KeyValue entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
17
6
|
require_relative "model"
|
|
18
|
-
|
|
19
|
-
# Register KeyValue transformation builders for all key-value formats
|
|
20
|
-
%i[json yaml toml hash].each do |format|
|
|
21
|
-
Lutaml::Model::TransformationRegistry.register_builder(
|
|
22
|
-
format, Lutaml::KeyValue::TransformationBuilder
|
|
23
|
-
)
|
|
24
|
-
end
|
|
7
|
+
require_relative "key_value/format"
|