json-schema-diff 0.2.0 → 0.2.1
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/CHANGELOG.md +9 -0
- data/README.md +1 -0
- data/lib/json/schema/diff/cli.rb +18 -0
- data/lib/json/schema/diff/comparer.rb +13 -0
- data/lib/json/schema/diff/formatter.rb +13 -0
- data/lib/json/schema/diff/schema_parser.rb +38 -0
- data/lib/json/schema/diff/version.rb +1 -1
- data/lib/json/schema/diff.rb +16 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 114ad725bbe219e05ad01ecbb7f419cf47a9d6e0e0861a3f65259ffe5ba08954
|
|
4
|
+
data.tar.gz: 34aa2c647ac5e9b6443788328af81dc8b26143641891e34d53b7cd732e711eb2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a26c6bd182618f38904058a803235b897257263fb012074fb609ba5c11b00835809cdf13fe1e0f963a00a5fb555c9a3cbd5eaebe8d41a43cb976deea839eefdf
|
|
7
|
+
data.tar.gz: c657e645bcbe47ad82a46c527b09a0013838569f807674b66af106c5b94ffebdb4b100b3573c4727354240e2b1b1b430601d77de8308bfec5266cfe69b70c7ca
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1] - 2025-01-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Comprehensive RDoc documentation for all classes and methods
|
|
15
|
+
- API documentation with @param and @return annotations
|
|
16
|
+
- Documentation URI in gemspec pointing to rubydoc.info
|
|
17
|
+
- Documentation badge in README
|
|
18
|
+
|
|
10
19
|
## [0.2.0] - 2025-01-26
|
|
11
20
|
|
|
12
21
|
### Added
|
data/README.md
CHANGED
|
@@ -4,6 +4,7 @@ A Ruby gem that performs semantic diffs between JSON files, using JSON Schema to
|
|
|
4
4
|
|
|
5
5
|
[](https://www.ruby-lang.org/)
|
|
6
6
|
[](https://rubygems.org/gems/json-schema-diff)
|
|
7
|
+
[](https://rubydoc.info/gems/json-schema-diff)
|
|
7
8
|
[](https://opensource.org/licenses/MIT)
|
|
8
9
|
|
|
9
10
|
Perfect for comparing structured CLI output from security tools like zizmor and capslock across versions to highlight when security issues have been introduced or resolved.
|
data/lib/json/schema/diff/cli.rb
CHANGED
|
@@ -3,11 +3,24 @@
|
|
|
3
3
|
module Json
|
|
4
4
|
module Schema
|
|
5
5
|
module Diff
|
|
6
|
+
# Command-line interface for json-schema-diff
|
|
7
|
+
#
|
|
8
|
+
# Provides a comprehensive CLI for comparing JSON files using JSON Schema guidance.
|
|
9
|
+
# Supports multiple output formats, validation options, and field filtering.
|
|
6
10
|
class CLI
|
|
11
|
+
# Entry point for the CLI application
|
|
12
|
+
#
|
|
13
|
+
# @param args [Array<String>] Command-line arguments
|
|
14
|
+
# @return [void]
|
|
7
15
|
def self.start(args)
|
|
8
16
|
new.run(args)
|
|
9
17
|
end
|
|
10
18
|
|
|
19
|
+
# Runs the CLI with the provided arguments
|
|
20
|
+
#
|
|
21
|
+
# @param args [Array<String>] Command-line arguments including schema, old JSON, and new JSON files
|
|
22
|
+
# @return [void]
|
|
23
|
+
# @raise [SystemExit] Exits with status 1 on errors
|
|
11
24
|
def run(args)
|
|
12
25
|
options = parse_options(args)
|
|
13
26
|
|
|
@@ -50,6 +63,11 @@ module Json
|
|
|
50
63
|
|
|
51
64
|
private
|
|
52
65
|
|
|
66
|
+
# Parses command-line options and arguments
|
|
67
|
+
#
|
|
68
|
+
# @param args [Array<String>] Command-line arguments to parse
|
|
69
|
+
# @return [Hash] Parsed options hash
|
|
70
|
+
# @raise [SystemExit] Exits on invalid options or help/version requests
|
|
53
71
|
def parse_options(args)
|
|
54
72
|
options = {
|
|
55
73
|
format: "pretty",
|
|
@@ -3,12 +3,25 @@
|
|
|
3
3
|
module Json
|
|
4
4
|
module Schema
|
|
5
5
|
module Diff
|
|
6
|
+
# Compares two JSON objects using schema guidance to detect changes
|
|
7
|
+
#
|
|
8
|
+
# This class performs recursive comparison of JSON structures, using schema
|
|
9
|
+
# information to provide context and handle special cases like read-only fields.
|
|
6
10
|
class Comparer
|
|
11
|
+
# Initialize a new Comparer
|
|
12
|
+
#
|
|
13
|
+
# @param schema_parser [SchemaParser] Parser for the JSON Schema
|
|
14
|
+
# @param ignore_fields [Array<String>] List of field paths to ignore during comparison
|
|
7
15
|
def initialize(schema_parser, ignore_fields = [])
|
|
8
16
|
@schema_parser = schema_parser
|
|
9
17
|
@ignore_fields = ignore_fields.map(&:to_s)
|
|
10
18
|
end
|
|
11
19
|
|
|
20
|
+
# Compares two JSON objects and returns a list of changes
|
|
21
|
+
#
|
|
22
|
+
# @param old_json [Object] The original JSON data
|
|
23
|
+
# @param new_json [Object] The new JSON data to compare against
|
|
24
|
+
# @return [Array<Hash>] Array of change objects with metadata
|
|
12
25
|
def compare(old_json, new_json)
|
|
13
26
|
changes = []
|
|
14
27
|
compare_recursive(old_json, new_json, "", changes)
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
module Json
|
|
4
4
|
module Schema
|
|
5
5
|
module Diff
|
|
6
|
+
# Formats diff results into human-readable or machine-readable output
|
|
7
|
+
#
|
|
8
|
+
# Supports both pretty-printed colorized output for humans and JSON output for machines.
|
|
9
|
+
# Handles ANSI color codes and provides structured formatting of change information.
|
|
6
10
|
class Formatter
|
|
11
|
+
# ANSI color codes for terminal output
|
|
7
12
|
COLORS = {
|
|
8
13
|
red: "\e[31m",
|
|
9
14
|
green: "\e[32m",
|
|
@@ -14,11 +19,19 @@ module Json
|
|
|
14
19
|
reset: "\e[0m"
|
|
15
20
|
}.freeze
|
|
16
21
|
|
|
22
|
+
# Initialize a new Formatter
|
|
23
|
+
#
|
|
24
|
+
# @param format [String] Output format - "pretty" or "json" (default: "pretty")
|
|
25
|
+
# @param use_color [Boolean] Whether to use ANSI color codes (default: true)
|
|
17
26
|
def initialize(format = "pretty", use_color = true)
|
|
18
27
|
@format = format
|
|
19
28
|
@use_color = use_color
|
|
20
29
|
end
|
|
21
30
|
|
|
31
|
+
# Formats an array of changes into the specified output format
|
|
32
|
+
#
|
|
33
|
+
# @param changes [Array<Hash>] Array of change objects from Comparer
|
|
34
|
+
# @return [String] Formatted output string
|
|
22
35
|
def format(changes)
|
|
23
36
|
case @format
|
|
24
37
|
when "json"
|
|
@@ -3,9 +3,19 @@
|
|
|
3
3
|
module Json
|
|
4
4
|
module Schema
|
|
5
5
|
module Diff
|
|
6
|
+
# Parses and validates JSON Schema files, extracting field metadata for diff guidance
|
|
7
|
+
#
|
|
8
|
+
# This class handles loading JSON Schema files, validating their structure,
|
|
9
|
+
# and providing methods to extract field information and detect noisy fields.
|
|
6
10
|
class SchemaParser
|
|
11
|
+
# @return [Hash] The parsed JSON Schema
|
|
7
12
|
attr_reader :schema
|
|
8
13
|
|
|
14
|
+
# Initialize a new SchemaParser with a JSON Schema file
|
|
15
|
+
#
|
|
16
|
+
# @param schema_file [String] Path to the JSON Schema file
|
|
17
|
+
# @param validate_schema [Boolean] Whether to validate the schema structure (default: true)
|
|
18
|
+
# @raise [Error] If the schema file is invalid or not found
|
|
9
19
|
def initialize(schema_file, validate_schema: true)
|
|
10
20
|
@schema = JSON.parse(File.read(schema_file))
|
|
11
21
|
|
|
@@ -18,6 +28,14 @@ module Json
|
|
|
18
28
|
raise Error, "Schema file not found: #{e.message}"
|
|
19
29
|
end
|
|
20
30
|
|
|
31
|
+
# Validates JSON data against the schema
|
|
32
|
+
#
|
|
33
|
+
# Performs basic structural validation to ensure JSON data types match schema expectations
|
|
34
|
+
# and required fields are present.
|
|
35
|
+
#
|
|
36
|
+
# @param json_data [Object] The JSON data to validate
|
|
37
|
+
# @return [Boolean] True if validation passes
|
|
38
|
+
# @raise [Error] If validation fails
|
|
21
39
|
def validate_json(json_data)
|
|
22
40
|
# Simple structural validation - check if JSON structure roughly matches schema expectations
|
|
23
41
|
begin
|
|
@@ -42,6 +60,10 @@ module Json
|
|
|
42
60
|
end
|
|
43
61
|
end
|
|
44
62
|
|
|
63
|
+
# Gets field information from the schema for a given path
|
|
64
|
+
#
|
|
65
|
+
# @param path [String] Dot-separated path to the field (e.g., "user.profile.name")
|
|
66
|
+
# @return [Hash] Field information including type, title, description, format, enum, and read_only
|
|
45
67
|
def get_field_info(path)
|
|
46
68
|
field_schema = traverse_schema(path.split('.'))
|
|
47
69
|
return {} unless field_schema
|
|
@@ -56,6 +78,14 @@ module Json
|
|
|
56
78
|
}
|
|
57
79
|
end
|
|
58
80
|
|
|
81
|
+
# Determines if a field is considered "noisy" and should potentially be ignored
|
|
82
|
+
#
|
|
83
|
+
# Noisy fields are those that change frequently but aren't meaningful for comparison,
|
|
84
|
+
# such as timestamps, UUIDs, or fields marked as readOnly in the schema.
|
|
85
|
+
#
|
|
86
|
+
# @param path [String] Dot-separated path to the field
|
|
87
|
+
# @param value [Object] The field value
|
|
88
|
+
# @return [Boolean] True if the field is considered noisy
|
|
59
89
|
def is_noisy_field?(path, value)
|
|
60
90
|
field_info = get_field_info(path)
|
|
61
91
|
format = field_info[:format]
|
|
@@ -77,6 +107,10 @@ module Json
|
|
|
77
107
|
|
|
78
108
|
private
|
|
79
109
|
|
|
110
|
+
# Validates that the schema has basic JSON Schema structure
|
|
111
|
+
#
|
|
112
|
+
# @return [void]
|
|
113
|
+
# @raise [Error] If the schema is missing basic structure
|
|
80
114
|
def validate_basic_schema_structure!
|
|
81
115
|
# Basic structural validation for schema
|
|
82
116
|
unless @schema.is_a?(Hash)
|
|
@@ -89,6 +123,10 @@ module Json
|
|
|
89
123
|
end
|
|
90
124
|
end
|
|
91
125
|
|
|
126
|
+
# Traverses the schema following a path to find field-specific schema information
|
|
127
|
+
#
|
|
128
|
+
# @param path_parts [Array<String>] Array of path components
|
|
129
|
+
# @return [Hash, nil] Schema for the field at the path, or nil if not found
|
|
92
130
|
def traverse_schema(path_parts)
|
|
93
131
|
current = @schema
|
|
94
132
|
|
data/lib/json/schema/diff.rb
CHANGED
|
@@ -9,9 +9,25 @@ require_relative "diff/schema_parser"
|
|
|
9
9
|
require_relative "diff/comparer"
|
|
10
10
|
require_relative "diff/formatter"
|
|
11
11
|
|
|
12
|
+
# JSON Schema Diff provides semantic diffing capabilities for JSON files using JSON Schema metadata.
|
|
13
|
+
#
|
|
14
|
+
# This gem allows you to compare two JSON files and get a rich diff output that is guided by
|
|
15
|
+
# a JSON Schema, providing type information, field metadata, and structured change detection.
|
|
16
|
+
#
|
|
17
|
+
# @example Basic usage
|
|
18
|
+
# Json::Schema::Diff::CLI.start(['schema.json', 'old.json', 'new.json'])
|
|
19
|
+
#
|
|
20
|
+
# @example Programmatic usage
|
|
21
|
+
# schema = Json::Schema::Diff::SchemaParser.new('schema.json')
|
|
22
|
+
# comparer = Json::Schema::Diff::Comparer.new(schema)
|
|
23
|
+
# diff = comparer.compare(old_data, new_data)
|
|
24
|
+
# formatter = Json::Schema::Diff::Formatter.new('pretty')
|
|
25
|
+
# puts formatter.format(diff)
|
|
12
26
|
module Json
|
|
13
27
|
module Schema
|
|
28
|
+
# The Diff module contains all functionality for JSON Schema-guided diffing
|
|
14
29
|
module Diff
|
|
30
|
+
# Base error class for all JSON Schema Diff errors
|
|
15
31
|
class Error < StandardError; end
|
|
16
32
|
end
|
|
17
33
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json-schema-diff
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Nesbitt
|
|
@@ -64,6 +64,7 @@ metadata:
|
|
|
64
64
|
homepage_uri: https://github.com/andrew/json-schema-diff
|
|
65
65
|
source_code_uri: https://github.com/andrew/json-schema-diff
|
|
66
66
|
changelog_uri: https://github.com/andrew/json-schema-diff/blob/main/CHANGELOG.md
|
|
67
|
+
documentation_uri: https://rubydoc.info/gems/json-schema-diff
|
|
67
68
|
rdoc_options: []
|
|
68
69
|
require_paths:
|
|
69
70
|
- lib
|