Class: Json::Merge::SmartMerger

Inherits:
Ast::Merge::SmartMergerBase
  • Object
show all
Includes:
Ast::Merge::Runtime::RootSessionSupport
Defined in:
lib/json/merge/smart_merger.rb

Overview

High-level merger for JSON / JSONC content.

Examples:

Basic usage

merger = SmartMerger.new(template_content, dest_content)
result = merger.merge
File.write("merged.json", result.output)

With options

merger = SmartMerger.new(template, dest,
  preference: :template,
  add_template_only_nodes: true)
result = merger.merge

Enable fuzzy matching

merger = SmartMerger.new(template, dest, match_refiner: ObjectMatchRefiner.new)

With regions (embedded content)

merger = SmartMerger.new(template, dest,
  regions: [{ detector: SomeDetector.new, merger_class: SomeMerger }])

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template_content, dest_content, signature_generator: nil, preference: :destination, add_template_only_nodes: false, remove_template_missing_nodes: false, corruption_handling: :heal, freeze_token: nil, match_refiner: nil, regions: nil, region_placeholder: nil, node_typing: nil, merge_arrays: true, preserve_atomic_formatting: false, dialect: :jsonc, **options) ⇒ SmartMerger

Creates a new SmartMerger

Parameters:

  • template_content (String)

    Template JSON content

  • dest_content (String)

    Destination JSON content

  • signature_generator (Proc, nil) (defaults to: nil)

    Custom signature generator

  • preference (Symbol, Hash) (defaults to: :destination)

    :destination, :template, or per-type Hash

  • add_template_only_nodes (Boolean) (defaults to: false)

    Whether to add nodes only found in template

  • remove_template_missing_nodes (Boolean) (defaults to: false)

    Whether to remove nodes missing from template

  • freeze_token (String, nil) (defaults to: nil)

    Token for freeze block markers

  • match_refiner (#call, nil) (defaults to: nil)

    Match refiner for fuzzy matching

  • regions (Array<Hash>, nil) (defaults to: nil)

    Region configurations for nested merging

  • region_placeholder (String, nil) (defaults to: nil)

    Custom placeholder for regions

  • node_typing (Hash{Symbol,String => #call}, nil) (defaults to: nil)

    Node typing configuration for per-node-type merge preferences

  • options (Hash)

    Additional options for forward compatibility



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/json/merge/smart_merger.rb', line 44

def initialize(
  template_content,
  dest_content,
  signature_generator: nil,
  preference: :destination,
  add_template_only_nodes: false,
  remove_template_missing_nodes: false,
  corruption_handling: :heal,
  freeze_token: nil,
  match_refiner: nil,
  regions: nil,
  region_placeholder: nil,
  node_typing: nil,
  merge_arrays: true,
  preserve_atomic_formatting: false,
  dialect: :jsonc,
  **options
)
  @remove_template_missing_nodes = remove_template_missing_nodes
  @corruption_handling = ::Ast::Merge::Healer.normalize_mode(corruption_handling)
  @merge_arrays = merge_arrays
  @preserve_atomic_formatting = preserve_atomic_formatting
  @dialect = dialect.to_sym
  unless %i[json jsonc json5].include?(@dialect)
    raise ArgumentError, "Unsupported JSON dialect #{dialect.inspect}. Expected json, jsonc, or json5."
  end

  super(
    template_content,
    dest_content,
    signature_generator: signature_generator,
    preference: preference,
    add_template_only_nodes: add_template_only_nodes,
    remove_template_missing_nodes: remove_template_missing_nodes,
    freeze_token: freeze_token,
    match_refiner: match_refiner,
    regions: regions,
    region_placeholder: region_placeholder,
    node_typing: node_typing,
    merge_arrays: merge_arrays,
    preserve_atomic_formatting: preserve_atomic_formatting,
    dialect: @dialect,
    **options
  )
end

Instance Attribute Details

#corruption_handlingObject (readonly)

Returns the value of attribute corruption_handling.



27
28
29
# File 'lib/json/merge/smart_merger.rb', line 27

def corruption_handling
  @corruption_handling
end

#dialectObject (readonly)

Returns the value of attribute dialect.



27
28
29
# File 'lib/json/merge/smart_merger.rb', line 27

def dialect
  @dialect
end

#runtime_sessionObject (readonly)

Returns the value of attribute runtime_session.



27
28
29
# File 'lib/json/merge/smart_merger.rb', line 27

def runtime_session
  @runtime_session
end

Instance Method Details

#merge_resultMergeResult

Perform the merge operation and return the full MergeResult object.

Returns:

  • (MergeResult)

    The merge result containing merged JSON content and metadata



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/json/merge/smart_merger.rb', line 109

def merge_result
  return @merge_result if @merge_result

  root_operation = start_runtime_session!
  @merge_result = super
  complete_runtime_session!(root_operation, @merge_result)
  @merge_result
rescue StandardError => e
  fail_runtime_session!(root_operation, e)
  raise
end

#merge_with_debugHash

Perform the merge and return detailed runtime-aware debug information.

Returns:

  • (Hash)

    Hash containing :content, :debug, :runtime, :statistics, and :decisions



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/json/merge/smart_merger.rb', line 124

def merge_with_debug
  result_obj = merge_result
  template_analysis_debug = {
    valid: @template_analysis.valid?,
    nodes: @template_analysis.nodes.size,
    freeze_blocks: @template_analysis.freeze_blocks.size
  }
  dest_analysis_debug = {
    valid: @dest_analysis.valid?,
    nodes: @dest_analysis.nodes.size,
    freeze_blocks: @dest_analysis.freeze_blocks.size
  }

  {
    content: result_obj.to_json,
    debug: {
      template_nodes: template_analysis_debug[:nodes],
      dest_nodes: dest_analysis_debug[:nodes],
      preference: @preference,
      add_template_only_nodes: @add_template_only_nodes,
      remove_template_missing_nodes: @remove_template_missing_nodes,
      corruption_handling: @corruption_handling,
      freeze_token: @freeze_token,
      runtime_operation_count: runtime_session&.operations&.size || 0,
      runtime_diagnostic_count: runtime_session&.diagnostics&.size || 0
    },
    runtime: runtime_session&.to_h,
    statistics: result_obj.statistics,
    decisions: result_obj.decision_summary,
    template_analysis: template_analysis_debug,
    dest_analysis: dest_analysis_debug
  }
end

#optionsHash

Backward-compatible options hash

Returns:

  • (Hash)

    The merge options



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/json/merge/smart_merger.rb', line 93

def options
  {
    preference: @preference,
    add_template_only_nodes: @add_template_only_nodes,
    remove_template_missing_nodes: @remove_template_missing_nodes,
    resolution_mode: @resolution_mode,
    unresolved_policy: @unresolved_policy.to_h,
    corruption_handling: @corruption_handling,
    match_refiner: @match_refiner,
    dialect: @dialect
  }
end