### Version Verification Example Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Illustrates how to retrieve the current serialization version and how to extract the version information from dumped binary data for compatibility checks during loading. ```ruby current_version = SyntaxTree::JSON::Serialization.version # => [0, 3, 0] # When loading, ensure version compatibility dumped = SyntaxTree::JSON.dump(json_source) # Extract version from dumped data magic, major, minor, patch = dumped.unpack("A4 I_3") if [major, minor, patch] != current_version puts "Warning: AST was serialized with version #{major}.#{minor}.#{patch}, current is #{current_version[0]}.#{current_version[1]}.#{current_version[2]}" end ``` -------------------------------- ### Complete JSON Parsing Example Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/parser.md A comprehensive example demonstrating the entire process of parsing a multi-line JSON string, accessing AST nodes, and handling potential parse errors. ```ruby require "syntax_tree/json" json_string = <<~JSON { "name": "Alice", "age": 30, "hobbies": ["reading", "coding"] } JSON begin parser = SyntaxTree::JSON::Parser.new(json_string) ast = parser.parse # Tree structure puts ast.class # => SyntaxTree::JSON::AST::Root puts ast.value.class # => SyntaxTree::JSON::AST::Object puts ast.value.values.length # => 3 (three key-value pairs) # First key name_key = ast.value.values[0][0] puts name_key.value # => "\"name\"" rescue SyntaxTree::JSON::Parser::ParseError => e puts "Parse error: #{e.message}" end ``` -------------------------------- ### Load Example Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Demonstrates creating a `Load` instance with source and dumped data, then calling `loaded` to reconstruct the AST. It also shows how to verify the reconstructed AST against the original parsed AST. ```ruby source = '{"x": 1, "y": [2, 3]}' dumped = SyntaxTree::JSON.dump(source) loader = SyntaxTree::JSON::Serialization::Load.new(source, dumped) reconstructed_ast = loader.loaded # Verify equivalence original_ast = SyntaxTree::JSON.parse(source) reconstructed_ast == original_ast # => true ``` -------------------------------- ### Storage and Transmission Example Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Demonstrates serializing an AST to binary format using `Dump` for efficient storage, writing it to a file, and later loading it back using `Load` with the original source. ```ruby # Serialize for storage original_source = '{"config": {"timeout": 5000, "retry": 3}}' ast = SyntaxTree::JSON.parse(original_source) dumper = SyntaxTree::JSON::Serialization::Dump.new ast.accept(dumper) # Store to file binary_ast = dumper.dumped File.binwrite("ast.bin", binary_ast) # Later, load back stored_binary = File.binread("ast.bin") loader = SyntaxTree::JSON::Serialization::Load.new(original_source, stored_binary) reloaded = loader.loaded ``` -------------------------------- ### Install SyntaxTree::JSON Gem Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/README.md Add the syntax_tree-json gem to your application's Gemfile for installation. ```ruby gem "syntax_tree-json" ``` -------------------------------- ### Comparing Format and PrettyPrint Visitors Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md This example contrasts the output of the Format visitor (valid JSON) with the PrettyPrint visitor (debug representation) for the same AST. ```ruby ast = SyntaxTree::JSON.parse('{"x": 1}') # Format produces valid JSON formatted = PrettierPrint.format(+"", 80) do |q| ast.accept(SyntaxTree::JSON::Format.new(q)) end puts formatted # => {"x": 1} # PrettyPrint produces debug output pp_output = PP.new(+"", 80) ast.accept(SyntaxTree::JSON::PrettyPrint.new(pp_output)) puts pp_output.output # => (root value=(object values={"x"=>(number value="1")})) ``` -------------------------------- ### Pretty Print JSON AST using Direct Visitor Usage Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md This example demonstrates direct usage of the PrettyPrint visitor. It involves parsing JSON, creating a PP output buffer, initializing the visitor, and accepting the AST. ```ruby require "pp" require "syntax_tree/json" ast = SyntaxTree::JSON.parse('{"x": true, "y": null}') output = PP.new(+"", 80) printer = SyntaxTree::JSON::PrettyPrint.new(output) ast.accept(printer) puts output.output ``` -------------------------------- ### Initialize Location AST Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Initializes a location with start and end byte offsets. Use this to create a new location object. ```ruby location = SyntaxTree::JSON::AST::Location.new(0, 5) location.start_offset # => 0 location.end_offset # => 5 ``` -------------------------------- ### Pretty Print JSON AST using Node#pretty_print Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md This example shows how to use the convenience method `pretty_print` available on all AST nodes to visualize a JSON structure. It requires the 'pp' and 'syntax_tree/json' gems. ```ruby require "pp" require "syntax_tree/json" ast = SyntaxTree::JSON.parse('{"items": [1, 2, 3]}') # Pretty print using the node's method ast.pretty_print(PP.new(STDOUT, 80)) ``` -------------------------------- ### Dump and Restore Round-Trip Example Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Shows a complete round-trip serialization process: parsing JSON to an AST, dumping it to binary, and then loading it back. It verifies that the original AST is equivalent to the reloaded AST. ```ruby require "syntax_tree/json" # Original JSON source = '{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}' # Parse and dump ast = SyntaxTree::JSON.parse(source) dumped = SyntaxTree::JSON.dump(source) puts "Original AST == Reloaded AST: #{ast == SyntaxTree::JSON.load(source, dumped)}" # => Original AST == Reloaded AST: true ``` -------------------------------- ### Get Dumped Binary AST Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Returns the complete binary-serialized AST. The binary string starts with the "STJN" header. ```ruby dumper.dumped ``` ```ruby ast = SyntaxTree::JSON.parse('{"name": "Alice"}') dumper = SyntaxTree::JSON::Serialization::Dump.new ast.accept(dumper) binary = dumper.dumped # Binary string starting with "STJN" header puts binary[0..3] # => "STJN" ``` -------------------------------- ### Custom Visitor: Collecting All String Values Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Example of creating a custom visitor by inheriting from SyntaxTree::JSON::Visitor to collect all string values from an AST. Override `visit_string` to process string nodes. ```ruby class StringCollector < SyntaxTree::JSON::Visitor attr_reader :strings def initialize @strings = [] end # Override for string nodes to collect values def visit_string(node) # node.value is the raw quoted string like "\"hello\"" strings << node.value end end ast = SyntaxTree::JSON.parse('{"name": "Alice", "city": "NYC"}') collector = StringCollector.new ast.accept(collector) puts collector.strings # => ["\"name\"", "\"Alice\"", "\"city\"", "\"NYC\""] ``` -------------------------------- ### Debugging Complex JSON Structures with Pretty Print Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md This example highlights the utility of PrettyPrint for visualizing deeply nested JSON structures, showing the complete tree with all node types and values. ```ruby complex_json = <<~JSON { "users": [ {"id": 1, "name": "Alice", "tags": ["admin", "user"]}, {"id": 2, "name": "Bob", "tags": ["user"]} ], "meta": {"count": 2, "version": "1.0"} } JSON ast = SyntaxTree::JSON.parse(complex_json) ast.pretty_print(PP.new(STDOUT, 100)) ``` -------------------------------- ### Custom JSON Formatting of Specific Nodes Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md Format only part of an AST by visiting specific nodes. This example formats only an object within a JSON array. ```ruby ast = SyntaxTree::JSON.parse('[1, 2, {"x": "y"}]') # Format only the object (third element) object_node = ast.value.values[2] formatted = PrettierPrint.format(+"", maxwidth: 40) do |q| object_node.accept(SyntaxTree::JSON::Format.new(q)) end puts formatted # => # { # "x": "y" # } ``` -------------------------------- ### Basic JSON Parsing Error Handling Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/errors.md Provides a basic example of parsing multiple JSON strings, catching `ParseError` for invalid ones, and printing success or error messages. Requires `syntax_tree/json` to be required. ```ruby require "syntax_tree/json" json_strings = [ '{"valid": true}', '{invalid}', '42 extra' ] json_strings.each do |source| begin ast = SyntaxTree::JSON.parse(source) puts "✓ Parsed: #{source}" rescue SyntaxTree::JSON::Parser::ParseError => e puts "✗ Error: #{e.message} in #{source}" end end # Output: # ✓ Parsed: {"valid": true} # ✗ Error: unexpected token: i in {invalid} # ✗ Error: unexpected tokens after value in 42 extra ``` -------------------------------- ### Custom Visitor: Counting Node Types Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Example of creating a custom visitor to count occurrences of different node types within an AST. Override specific `visit_` methods and call `super` for nodes with children. ```ruby class NodeCounter < SyntaxTree::JSON::Visitor attr_reader :counts def initialize @counts = Hash.new(0) end def visit_root(node) counts[:root] += 1 super end def visit_object(node) counts[:object] += 1 super end def visit_array(node) counts[:array] += 1 super end def visit_string(node) counts[:string] += 1 end def visit_number(node) counts[:number] += 1 end end source = '{"items": [1, "two", {"value": 3}]}' ast = SyntaxTree::JSON.parse(source) counter = NodeCounter.new ast.accept(counter) puts counter.counts # => {:root=>1, :object=>2, :array=>1, :string=>2, :number=>2} ``` -------------------------------- ### Location Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Represents the position of an AST node within the source string, storing start and end byte offsets. ```APIDOC ## Class: SyntaxTree::JSON::AST::Location ### Description Represents the position of an AST node within the source string. ### Initializer #### Location#initialize Initializes a location with start and end byte offsets. **Parameters:** | Parameter | Type | Default | Description | |--------------|---------|---------|------------------------------------------------| | start_offset | Integer | — | Starting byte offset in source (0-indexed) | | end_offset | Integer | — | Ending byte offset in source (exclusive) | **Returns:** `Location` **Example:** ```ruby location = SyntaxTree::JSON::AST::Location.new(0, 5) location.start_offset # => 0 location.end_offset # => 5 ``` ### Methods #### Location#to Creates a new location spanning from this location's start to another location's end. **Parameters:** | Parameter | Type | Default | Description | |-----------|----------|---------|---------------------------------------| | other | Location | — | Target location with the ending offset | **Returns:** `Location` — New location from this start_offset to other's end_offset **Example:** ```ruby loc1 = SyntaxTree::JSON::AST::Location.new(0, 5) loc2 = SyntaxTree::JSON::AST::Location.new(5, 10) combined = loc1.to(loc2) combined.start_offset # => 0 combined.end_offset # => 10 ``` #### Location#to_range Converts the location to a Ruby Range suitable for string slicing. **Returns:** `Range` — Exclusive range (start_offset...end_offset) **Example:** ```ruby source = '{"name": "Alice"}' location = SyntaxTree::JSON::AST::Location.new(2, 8) source[location.to_range] # => "name":" ``` ``` -------------------------------- ### Initialize PrettyPrint Visitor Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md Creates a pretty printer instance that outputs to the provided Ruby PP printer object. Requires 'pp' and 'syntax_tree/json' gems. ```ruby require "pp" require "syntax_tree/json" ast = SyntaxTree::JSON.parse('{"x": 1}') # Create a pretty printer and visit the AST pp_printer = SyntaxTree::JSON::PrettyPrint.new(PP.new(STDOUT, 80)) ast.accept(pp_printer) # Output: # (root value=(object values={ # "x"=>(number value="1")})) ``` -------------------------------- ### Get Serialization Library Version Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Returns the library version as an array of three integers [major, minor, patch]. ```ruby module SyntaxTree::JSON::Serialization def self.version # Returns version as array of integers end end ``` ```ruby SyntaxTree::JSON::Serialization.version ``` ```ruby version = SyntaxTree::JSON::Serialization.version # => [0, 3, 0] major, minor, patch = version puts "Version: #{major}.#{minor}.#{patch}" # => Version: 0.3.0 ``` -------------------------------- ### SyntaxTree::JSON::Serialization::Dump#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Creates a new dumper instance, initializing an internal binary output buffer and writing the magic header and version information. ```APIDOC ## SyntaxTree::JSON::Serialization::Dump#initialize ### Description Creates a new dumper with an empty binary buffer. ### Method `SyntaxTree::JSON::Serialization::Dump.new` ### Returns `Dump` ### Behavior - Initializes an internal StringIO buffer - Writes the magic header "STJN" (4 bytes) - Writes version numbers as three unsigned long integers (12 bytes total) - Total header: 16 bytes ### Example ```ruby dumper = SyntaxTree::JSON::Serialization::Dump.new # Verify header was written dumper.output.string[0..3] # => "STJN" # Extract version from header magic, major, minor, patch = dumper.output.string.unpack("A4 I_3") # => ["STJN", 0, 3, 0] ``` ``` -------------------------------- ### Initialize SyntaxTree::JSON::Format Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md Creates a formatter instance that outputs to a given PrettierPrint printer. This is used to set up the formatting environment. ```ruby SyntaxTree::JSON::Format.new(q) ``` ```ruby require "prettier_print" # Create a formatter output = "" PrettierPrint.format(output, maxwidth: 80) do |q| formatter = SyntaxTree::JSON::Format.new(q) # Now use the formatter with AST nodes end ``` -------------------------------- ### Define Location AST Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Represents the position of an AST node within the source string. It stores start and end byte offsets. ```ruby class SyntaxTree::JSON::AST::Location attr_reader :start_offset # Integer attr_reader :end_offset # Integer end ``` -------------------------------- ### SyntaxTree::JSON::PrettyPrint.new Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md Initializes a new PrettyPrint visitor. This visitor generates human-readable debug output of Abstract Syntax Tree nodes. ```APIDOC ## SyntaxTree::JSON::PrettyPrint.new ### Description Creates a pretty printer that outputs to the given PP printer. ### Method `new(q)` ### Parameters #### Path Parameters - **q** (PP) - Required - Ruby PP printer object for debug output ### Response #### Success Response - **PrettyPrint** - Returns the initialized PrettyPrint object. ### Request Example ```ruby require "pp" require "syntax_tree/json" ast = SyntaxTree::JSON.parse('{"x": 1}') # Create a pretty printer and visit the AST pp_printer = SyntaxTree::JSON::PrettyPrint.new(PP.new(STDOUT, 80)) ast.accept(pp_printer) # Output: # (root value=(object values={ # "x"=>(number value="1")})) ``` ``` -------------------------------- ### Initialize Dump Visitor Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Creates a new dumper with an empty binary buffer. Initializes an internal StringIO buffer, writes the magic header "STJN" (4 bytes), and version numbers as three unsigned long integers (12 bytes total). Total header is 16 bytes. ```ruby class SyntaxTree::JSON::Serialization::Dump < Visitor attr_reader :output # StringIO - binary output buffer end ``` ```ruby SyntaxTree::JSON::Serialization::Dump.new ``` ```ruby dumper = SyntaxTree::JSON::Serialization::Dump.new # Verify header was written dumper.output.string[0..3] # => "STJN" # Extract version from header magic, major, minor, patch = dumper.output.string.unpack("A4 I_3") # => ["STJN", 0, 3, 0] ``` -------------------------------- ### Preserving Escape Sequences during JSON Formatting Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md The formatter preserves original escape sequences from the source. This example shows how backslashes in a path string are maintained. ```ruby source = '{"path": "C:\\Users\\Alice"}' formatted = SyntaxTree::JSON.format(source) # Output preserves the original escaping puts formatted # => {"path": "C:\\Users\\Alice"} ``` -------------------------------- ### SyntaxTree::JSON::Parser#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/parser.md Initializes a new parser instance with the provided JSON source code string. This is the entry point for parsing. ```APIDOC ## SyntaxTree::JSON::Parser#initialize ### Description Creates a parser for the given JSON source code. ### Method `SyntaxTree::JSON::Parser.new(source)` ### Parameters #### Path Parameters - **source** (String) - Required - JSON source code to parse ### Request Example ```ruby parser = SyntaxTree::JSON::Parser.new('{"name": "Alice"}') ``` ### Response #### Success Response (200) - **Parser** - Returns a new Parser instance. ### Response Example ```ruby parser = SyntaxTree::JSON::Parser.new('{"name": "Alice"}') parser.source # => '{"name": "Alice"}' ``` ``` -------------------------------- ### SyntaxTree::JSON::Format#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md Initializes a new formatter instance that will output to the provided PrettierPrint printer object. This printer manages indentation and line breaks. ```APIDOC ## SyntaxTree::JSON::Format#initialize ### Description Creates a formatter that outputs to the given PrettierPrint printer. ### Method `SyntaxTree::JSON::Format.new(q)` ### Parameters #### Path Parameters * **q** (PrettierPrint) - Required - Printer object managing line breaks and indentation ### Request Example ```ruby require "prettier_print" output = "" PrettierPrint.format(output, maxwidth: 80) do |q| formatter = SyntaxTree::JSON::Format.new(q) # Now use the formatter with AST nodes end ``` ### Response #### Success Response Returns: `Format` ``` -------------------------------- ### Create New Location from Two Locations Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates a new location spanning from this location's start to another location's end. Useful for combining adjacent or overlapping ranges. ```ruby loc1 = SyntaxTree::JSON::AST::Location.new(0, 5) loc2 = SyntaxTree::JSON::AST::Location.new(5, 10) combined = loc1.to(loc2) combined.start_offset # => 0 combined.end_offset # => 10 ``` -------------------------------- ### Load#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Creates a loader that will deserialize from the given binary data. It requires the original source code to reconstruct location-dependent values. ```APIDOC ## Load#initialize Creates a loader that will deserialize from the given binary data. ```ruby SyntaxTree::JSON::Serialization::Load.new(source, dumped) ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | source | String | — | Original JSON source code (used to extract string/number values) | | dumped | String | — | Binary serialized AST from Dump (starting with "STJN") | ### Returns `Load` ### Example ```ruby source = '{"name": "Alice"}' dumped = SyntaxTree::JSON.dump(source) # Create a loader loader = SyntaxTree::JSON::Serialization::Load.new(source, dumped) ``` ``` -------------------------------- ### AST Node Integration with Visitor Pattern Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Demonstrates how AST nodes use the `accept` method to dispatch to the appropriate visitor method. This enables the visitor pattern for tree traversal. ```ruby ast = SyntaxTree::JSON.parse('[1, 2]') # Calling accept on a node dispatches to the visitor visitor = SyntaxTree::JSON::Visitor.new ast.accept(visitor) # Calls visitor.visit_root(ast) ast.value.accept(visitor) # Calls visitor.visit_array(ast.value) ast.value.values[0].accept(visitor) # Calls visitor.visit_number(...) ``` -------------------------------- ### Initialize Load Class Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Creates a loader instance for deserializing binary AST data. Requires the original source string and the binary dumped data. ```ruby SyntaxTree::JSON::Serialization::Load.new(source, dumped) ``` -------------------------------- ### CLI: Write JSON with SyntaxTree Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/README.md Use the 'stree write' command with the 'json' plugin to write a JSON file. ```sh $ stree write --plugins=json file.json file.json 1ms ``` -------------------------------- ### Initialize Root AST Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates a Root node wrapping a JSON value and its location. The value can be any valid JSON AST node type. ```ruby value_node = SyntaxTree::JSON::AST::String.new( value: '"hello"', location: SyntaxTree::JSON::AST::Location.new(0, 7) ) root = SyntaxTree::JSON::AST::Root.new( value: value_node, location: SyntaxTree::JSON::AST::Location.new(0, 7) ) root.value # => # ``` -------------------------------- ### SyntaxTree::JSON::Serialization::Dump#dumped Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Returns the complete binary-serialized Abstract Syntax Tree from the internal buffer. ```APIDOC ## SyntaxTree::JSON::Serialization::Dump#dumped ### Description Returns the complete binary-serialized AST. ### Method `dumper.dumped` ### Returns `String` — Binary representation of the dumped AST ### Example ```ruby ast = SyntaxTree::JSON.parse('{"name": "Alice"}') dumper = SyntaxTree::JSON::Serialization::Dump.new ast.accept(dumper) binary = dumper.dumped # Binary string starting with "STJN" header puts binary[0..3] # => "STJN" ``` ``` -------------------------------- ### Create a Null Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Demonstrates how to instantiate a Null node for the JSON AST, specifying its location in the source. ```ruby null_node = SyntaxTree::JSON::AST::Null.new( location: SyntaxTree::JSON::AST::Location.new(0, 4) ) ``` -------------------------------- ### Object#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates an Object node representing a JSON object. It takes an array of key-value pairs and a location. ```APIDOC ## Object#initialize ### Description Creates an Object node representing a JSON object. It takes an array of key-value pairs and a location. ### Parameters #### Parameters - **values** (Array) - Required - Array of [key_node, value_node] pairs where key is String node - **location** (Location) - Required - Position spanning entire object ### Returns `Object` ### Example ```ruby key = SyntaxTree::JSON::AST::String.new( value: '"name"', location: SyntaxTree::JSON::AST::Location.new(2, 8) ) value = SyntaxTree::JSON::AST::String.new( value: '"Alice"', location: SyntaxTree::JSON::AST::Location.new(10, 17) ) obj = SyntaxTree::JSON::AST::Object.new( values: [[key, value]], location: SyntaxTree::JSON::AST::Location.new(0, 19) ) obj.values # => [[#, #]] ``` ``` -------------------------------- ### Using Node.format for JSON Formatting Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md AST nodes include a convenience `format` method that wraps the Format visitor, providing a simpler way to format the node. ```ruby ast = SyntaxTree::JSON.parse('{"x": 1}') formatted = PrettierPrint.format(+"", maxwidth: 80) do |q| ast.format(q) # Equivalent to ast.accept(Format.new(q)) end puts formatted ``` -------------------------------- ### CLI: Format JSON with SyntaxTree Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/README.md Use the 'stree format' command with the 'json' plugin to format a JSON file. ```sh $ stree format --plugins=json file.json { "Hello": "world!" } ``` -------------------------------- ### Define SyntaxTree::JSON::Format Class Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md Defines the SyntaxTree::JSON::Format class, inheriting from Visitor. It exposes an attribute 'q' for the PrettierPrint output printer. ```ruby class SyntaxTree::JSON::Format < Visitor attr_reader :q # PrettierPrint - the output printer end ``` -------------------------------- ### Storage and Transmission Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Illustrates using the `Dump` visitor for efficient storage of ASTs. The serialized binary data can be stored to a file and later loaded back. ```APIDOC ### Storage and Transmission The Dump visitor can be used for efficient storage: ```ruby # Serialize for storage original_source = '{"config": {"timeout": 5000, "retry": 3}}' ast = SyntaxTree::JSON.parse(original_source) dumper = SyntaxTree::JSON::Serialization::Dump.new ast.accept(dumper) # Store to file binary_ast = dumper.dumped File.binwrite("ast.bin", binary_ast) # Later, load back stored_binary = File.binread("ast.bin") loader = SyntaxTree::JSON::Serialization::Load.new(original_source, stored_binary) reloaded = loader.loaded ``` ``` -------------------------------- ### CLI: Parse JSON to AST with SyntaxTree Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/README.md Use the 'stree ast' command with the 'json' plugin to parse a JSON file into an Abstract Syntax Tree. ```sh $ stree ast --plugins=json file.json (root object=(object values={"Hello"=>(literal value="world!")})) ``` -------------------------------- ### SyntaxTree::JSON Module Methods Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md The main entry point for interacting with the syntax_tree-json gem. It provides methods to parse JSON strings into Abstract Syntax Trees (AST), format JSON source code, dump ASTs into a binary string representation, load ASTs from binary data, and read JSON from files. ```APIDOC ## Module: SyntaxTree::JSON ### Description Provides core functionality for parsing, formatting, serializing, and reading JSON. ### Methods #### `parse(source)` - **Description**: Parses a JSON string into an AST::Root object. - **Returns**: AST::Root #### `format(source, maxwidth: 80)` - **Description**: Formats a JSON string according to specified width constraints. - **Parameters**: - `source` (String) - The JSON string to format. - `maxwidth` (Integer) - Optional. The maximum width for formatting. Defaults to 80. - **Returns**: String #### `dump(source)` - **Description**: Serializes an AST (derived from the source JSON) into a binary string. - **Parameters**: - `source` (String) - The JSON string to serialize. - **Returns**: String #### `load(source, dumped)` - **Description**: Deserializes a binary AST representation back into an AST::Root object, using the original source for context. - **Parameters**: - `source` (String) - The original JSON source string. - `dumped` (String) - The binary string representation of the AST. - **Returns**: AST::Root #### `read(filepath)` - **Description**: Reads JSON content from a file specified by its path. - **Parameters**: - `filepath` (String) - The path to the JSON file. - **Returns**: String ``` -------------------------------- ### Initialize SyntaxTree::JSON::Parser Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/parser.md Creates a new parser instance for a given JSON source string. The source string is stored and accessible via the `source` attribute. ```ruby SyntaxTree::JSON::Parser.new(source) ``` ```ruby parser = SyntaxTree::JSON::Parser.new('{"name": "Alice"}') parser.source # => '{"name": "Alice"}' ``` -------------------------------- ### Visitor#visit Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Dispatches a node to the appropriate visit method by calling the node's `accept` method. It handles visiting a single AST node or nil. ```APIDOC ## Visitor#visit ### Description Dispatches a node to the appropriate visit method by calling the node's `accept` method. It handles visiting a single AST node or nil. ### Method `visitor.visit(node)` ### Parameters #### Path Parameters - **node** (Node | nil) - Required - AST node to visit, or nil ### Returns The return value of the node's visitor method (visitor-specific) ### Request Example ```ruby visitor = SyntaxTree::JSON::Visitor.new ast = SyntaxTree::JSON.parse('{"name": "Alice"}') # Visit the root result = visitor.visit(ast) # => nil (default visitor returns nil) # Visit returns nil if node is nil result = visitor.visit(nil) # => nil ``` ``` -------------------------------- ### Format JSON using SyntaxTree::JSON.format Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md The recommended way to format JSON is through the SyntaxTree::JSON.format method. It takes the source string and formatting options like maxwidth. ```ruby source = '{"name":"Alice","age":30}' formatted = SyntaxTree::JSON.format(source, maxwidth: 60) puts formatted # Output: # { # "name": "Alice", # "age": 30 # } ``` -------------------------------- ### Create a JSON Object Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Initializes an Object node with key-value pairs. Each key must be a String node. ```ruby key = SyntaxTree::JSON::AST::String.new( value: '"name"', location: SyntaxTree::JSON::AST::Location.new(2, 8) ) value = SyntaxTree::JSON::AST::String.new( value: '"Alice"', location: SyntaxTree::JSON::AST::Location.new(10, 17) ) obj = SyntaxTree::JSON::AST::Object.new( values: [[key, value]], location: SyntaxTree::JSON::AST::Location.new(0, 19) ) obj.values # => [[#, #]] ``` -------------------------------- ### Load#loaded Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Deserializes the binary AST and returns the reconstructed root node. It performs version verification and throws a TypeError if the magic header or versions do not match. ```APIDOC ### Load#loaded Deserializes the binary AST and returns the reconstructed root node. ```ruby loader.loaded ``` ### Returns `SyntaxTree::JSON::AST::Root` — Reconstructed AST ### Throws `TypeError` — If the magic header doesn't match "STJN" or versions don't match ### Example ```ruby source = '{"x": 1, "y": [2, 3]}' dumped = SyntaxTree::JSON.dump(source) loader = SyntaxTree::JSON::Serialization::Load.new(source, dumped) reconstructed_ast = loader.loaded # Verify equivalence original_ast = SyntaxTree::JSON.parse(source) reconstructed_ast == original_ast # => true ``` ``` -------------------------------- ### String#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates a String node for a JSON string value. It requires the raw string value and its location. ```APIDOC ## String#initialize ### Description Creates a String node for a JSON string value. It requires the raw string value and its location. ### Parameters #### Parameters - **value** (String) - Required - Raw string value including surrounding quotes and escape sequences - **location** (Location) - Required - Position of string in source ### Returns `String` ### Example ```ruby string = SyntaxTree::JSON::AST::String.new( value: '"hello world"', location: SyntaxTree::JSON::AST::Location.new(0, 13) ) string.value # => "hello world" ``` ``` -------------------------------- ### Null#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates a Null node for the Syntax Tree JSON AST. It requires a location parameter indicating the position of 'null' in the source code. ```APIDOC ## Null#initialize ### Description Creates a Null node. ### Parameters #### Path Parameters - **location** (Location) - Required - Position of `null` in source ### Returns `Null` ### Request Example ```ruby null_node = SyntaxTree::JSON::AST::Null.new( location: SyntaxTree::JSON::AST::Location.new(0, 4) ) ``` ``` -------------------------------- ### Array#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates an Array node representing a JSON array. It accepts an array of nodes and a location. ```APIDOC ## Array#initialize ### Description Creates an Array node representing a JSON array. It accepts an array of nodes and a location. ### Parameters #### Parameters - **values** (Array) - Required - Array of Node objects representing JSON values - **location** (Location) - Required - Position spanning entire array ### Returns `Array` ### Example ```ruby string_node = SyntaxTree::JSON::AST::String.new( value: '"hello"', location: SyntaxTree::JSON::AST::Location.new(1, 8) ) number_node = SyntaxTree::JSON::AST::Number.new( value: '42', location: SyntaxTree::JSON::AST::Location.new(10, 12) ) array = SyntaxTree::JSON::AST::Array.new( values: [string_node, number_node], location: SyntaxTree::JSON::AST::Location.new(0, 13) ) array.values # => [#, #] ``` ``` -------------------------------- ### Direct JSON Formatting with PrettierPrint Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md For advanced control, use the Format visitor directly with PrettierPrint. This involves parsing the source to an AST and then accepting the Format visitor. ```ruby require "prettier_print" require "syntax_tree/json" source = '{"name":"Alice","hobbies":["reading","coding"]}' ast = SyntaxTree::JSON.parse(source) output = PrettierPrint.format(+"", maxwidth: 50) do |q| ast.accept(SyntaxTree::JSON::Format.new(q)) end puts output ``` -------------------------------- ### Register JSON Handler for CLI Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/syntax_tree_json.md Demonstrates how the SyntaxTree::JSON module is registered to handle .json files with Syntax Tree CLI tools. This enables commands like 'stree ast --plugins=json file.json'. ```bash # With the gem installed and required, you can use: stree ast --plugins=json file.json stree format --plugins=json file.json stree write --plugins=json file.json ``` -------------------------------- ### Pretty Print AST Node with PP Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Prints this AST node using the PrettyPrint visitor and a Ruby PP printer for debug output. Useful for inspecting the structure of the AST. ```ruby ast = SyntaxTree::JSON.parse('{"name": "Alice"}') ast.pretty_print(PP.new(STDOUT, 80)) # => (root value=(object values={"name"=>(string value="Alice")})) ``` -------------------------------- ### Version Verification Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Explains how to check the current serialization version and perform version compatibility checks when loading dumped AST data. ```APIDOC ### Version Verification ```ruby current_version = SyntaxTree::JSON::Serialization.version # => [0, 3, 0] # When loading, ensure version compatibility dumped = SyntaxTree::JSON.dump(json_source) # Extract version from dumped data magic, major, minor, patch = dumped.unpack("A4 I_3") if [major, minor, patch] != current_version puts "Warning: AST was serialized with version #{major}.#{minor}.#{patch}, current is #{current_version[0]}.#{current_version[1]}.#{current_version[2]}" end ``` ``` -------------------------------- ### Define SyntaxTree::JSON::PrettyPrint Class Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md Defines the PrettyPrint class, inheriting from Visitor and exposing the PP printer object. ```ruby class SyntaxTree::JSON::PrettyPrint < Visitor attr_reader :q # PP - the Ruby PP printer object end ``` -------------------------------- ### Dispatch Node Visit with Visitor#visit Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Use `visitor.visit(node)` to dispatch a node to its appropriate visit method by calling the node's `accept` method. The default visitor returns nil. ```ruby visitor = SyntaxTree::JSON::Visitor.new ast = SyntaxTree::JSON.parse('{"name": "Alice"}') # Visit the root result = visitor.visit(ast) # => nil (default visitor returns nil) # Visit returns nil if node is nil result = visitor.visit(nil) # => nil ``` -------------------------------- ### Serialize and Restore AST Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md Use these snippets to serialize an AST to a binary string and later restore it. This is useful for efficient storage or transmission of AST data. The restored AST can be compared to a freshly parsed AST. ```ruby # Serialize to binary dumped = SyntaxTree::JSON.dump(source) # Later: restore from binary + original source restored = SyntaxTree::JSON.load(source, dumped) restored == SyntaxTree::JSON.parse(source) # true ``` -------------------------------- ### PrettyPrint#visit_root Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/pretty_print.md Pretty prints a Root node, displaying its value in a Lisp-like format. ```APIDOC ## PrettyPrint#visit_root ### Description Pretty prints a Root node showing its value. ### Method `visit_root(node)` ### Parameters #### Path Parameters - **node** (AST::Root) - Required - Root node to display ### Response #### Success Response - **nil** - This method does not return a value. ### Output Format `(root value=)` ### Request Example ```ruby ast = SyntaxTree::JSON.parse('{"x": 1}') output = PP.new(+"", 80) SyntaxTree::JSON::PrettyPrint.new(output).visit_root(ast) puts output.output # => (root value=(object values={"x"=>(number value="1")})) ``` ``` -------------------------------- ### Visitor#visit_root Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Visits a Root node and its value. This method is the entry point for visiting the entire AST structure. ```APIDOC ## Visitor#visit_root ### Description Visits a Root node and its value. This method is the entry point for visiting the entire AST structure. ### Method `visitor.visit_root(node)` ### Parameters #### Path Parameters - **node** (AST::Root) - Required - Root node to visit ### Returns Result from visiting child nodes ``` -------------------------------- ### Load AST from Binary and Source Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/syntax_tree_json.md Reconstructs a JSON AST from its binary-serialized representation and the original source code. This is useful for deserializing previously dumped ASTs, preserving location information. ```ruby source = '{"name": "Alice"}' dumped = SyntaxTree::JSON.dump(source) # Later, reconstruct the AST from the binary and source reloaded = SyntaxTree::JSON.load(source, dumped) # => # # The reloaded AST is equivalent to the original original = SyntaxTree::JSON.parse(source) reloaded == original # => true ``` -------------------------------- ### Serialization Module Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md Handles the binary encoding and decoding of Abstract Syntax Trees, preserving location information. It includes constants for directives and visitors for both dumping (encoding) and loading (decoding) the AST. ```APIDOC ## Module: SyntaxTree::JSON::Serialization ### Description Provides functionality for binary serialization and deserialization of Abstract Syntax Trees, including location data. ### Components #### `Directive` (Constants) - **Description**: Contains constants used in the binary serialization format. #### `Dump` (Visitor) - **Description**: A visitor responsible for the binary encoding (dumping) of the AST. #### `Load` - **Description**: Responsible for reconstructing the AST from its binary representation. ``` -------------------------------- ### Format JSON Source Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md This snippet demonstrates how to format JSON source code using the `format` method, optionally specifying a maximum line width. It helps in pretty-printing JSON strings. ```ruby formatted = SyntaxTree::JSON.format(source, maxwidth: 60) ``` -------------------------------- ### Dump and Restore Round-Trip Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Demonstrates a full round-trip serialization and deserialization process, parsing JSON, dumping it to binary, and then loading it back to verify equivalence. ```APIDOC ## Dump and Restore Round-Trip ```ruby require "syntax_tree/json" # Original JSON source = '{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}' # Parse and dump ast = SyntaxTree::JSON.parse(source) dumped = SyntaxTree::JSON.dump(source) puts "Original AST == Reloaded AST: #{ast == SyntaxTree::JSON.load(source, dumped)}" # => Original AST == Reloaded AST: true ``` ``` -------------------------------- ### SyntaxTree::JSON.format Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/format.md The recommended way to format JSON using the Syntax Tree library. ```APIDOC ## SyntaxTree::JSON.format ### Description Formats a JSON source string. ### Method `SyntaxTree::JSON.format(source, maxwidth: nil)` ### Parameters #### Query Parameters - **source** (string) - Required - The JSON source string to format. - **maxwidth** (integer) - Optional - The maximum width for formatting. ``` -------------------------------- ### Visit All Nodes in a Collection with Visitor#visit_all Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/visitor.md Use `visitor.visit_all(nodes)` to visit each node in a collection and return an array of the results. The default visitor returns nil for each element. ```ruby visitor = SyntaxTree::JSON::Visitor.new ast = SyntaxTree::JSON.parse('[1, 2, 3]') array_node = ast.value results = visitor.visit_all(array_node.values) # => [nil, nil, nil] (default visitor returns nil for each) ``` -------------------------------- ### Create a JSON String Node Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Initializes a String node with its raw value, including quotes and escape sequences. ```ruby string = SyntaxTree::JSON::AST::String.new( value: '"hello world"', location: SyntaxTree::JSON::AST::Location.new(0, 13) ) string.value # => "\"hello world\"" ``` -------------------------------- ### SyntaxTree::JSON::Serialization::Dump#visit_root Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/serialization.md Serializes a root node, writing its directive code, location, and the contained value node. ```APIDOC ## SyntaxTree::JSON::Serialization::Dump#visit_root ### Description Serializes a root node. ### Method `dumper.visit_root(node)` ### Writes - Directive: "R" (1 byte) - Location: start_offset and end_offset (8 bytes) - Child: the contained value node (variable) ``` -------------------------------- ### Null#initialize Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Creates a Null node representing a JSON `null` value. It requires the location of the value in the source. ```APIDOC ## Null#initialize ### Description Creates a Null node representing a JSON `null` value. It requires the location of the value in the source. ### Parameters #### Parameters - **location** (Location) - Required - Position of `null` in source ### Returns `Null` ``` -------------------------------- ### Implement Custom Operations with Visitor Pattern Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md Custom operations like formatting, transformation, or validation can be implemented as visitors that traverse the AST. This allows for modular and extensible code. ```ruby # Format: visits nodes and outputs JSON format = Format.new(printer) ast.accept(format) # PrettyPrint: visits nodes and outputs debug representation debug = PrettyPrint.new(pp_printer) ast.accept(debug) ``` -------------------------------- ### SyntaxTree::JSON::Parser#parse Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/parser.md Parses the JSON source code provided during initialization and returns the Abstract Syntax Tree (AST) root node. ```APIDOC ## SyntaxTree::JSON::Parser#parse ### Description Parses the source code and returns the root AST node. ### Method `parser.parse` ### Parameters This method does not accept any parameters. ### Response #### Success Response (200) - **SyntaxTree::JSON::AST::Root** - The root node of the parsed JSON tree. ### Throws - **SyntaxTree::JSON::Parser::ParseError** - If the JSON is malformed. ### Request Example ```ruby parser = SyntaxTree::JSON::Parser.new('[1, 2, 3]') ast = parser.parse ``` ### Response Example ```ruby ast.value.values # => [#, #, #] ``` ``` -------------------------------- ### Pattern Matching on JSON AST Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/api-reference/ast.md Shows how to use Ruby's pattern matching with `deconstruct` and `deconstruct_keys` to traverse and analyze the JSON AST structure. ```ruby ast = SyntaxTree::JSON.parse('{"name": "Alice"}') # Pattern match on the structure case ast in SyntaxTree::JSON::AST::Root[value: obj_node] # obj_node is the Object node case obj_node in SyntaxTree::JSON::AST::Object[values: [[key, val]]] # key and val are accessible end end # Use in conditionals if ast in SyntaxTree::JSON::AST::Root[value: SyntaxTree::JSON::AST::Object] puts "Root contains an object" end ``` -------------------------------- ### Visitor Base Class Source: https://github.com/ruby-syntax-tree/syntax_tree-json/blob/main/_autodocs/README.md Provides the base implementation for the Visitor pattern, allowing for custom traversal and manipulation of the AST. Subclasses can override specific `visit_*` methods to implement custom logic for different AST node types. ```APIDOC ## Class: SyntaxTree::JSON::Visitor ### Description Base class for implementing the Visitor pattern to traverse the Abstract Syntax Tree. ### Methods #### `visit(node)` - **Description**: Visits a single AST node. #### `visit_all(nodes)` - **Description**: Visits all nodes in a collection. #### `visit_child_nodes(node)` - **Description**: Visits all child nodes of a given node. #### `visit_* (for each node type)` - **Description**: Placeholder methods for specific AST node types (e.g., `visit_string`, `visit_object`) that can be overridden by subclasses to provide custom behavior during traversal. ```