Created
April 14, 2025 17:41
-
-
Save peterc/413c94b211b3ec4cf975ae2d36188c16 to your computer and use it in GitHub Desktop.
Revisions
-
peterc created this gist
Apr 14, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,272 @@ # JSON Library for Ruby The JSON library is a comprehensive and robust solution for parsing, generating, and manipulating JSON data in Ruby. It offers full support for JSON encoding and decoding, including extensions for common Ruby types like `Date`, `Time`, `Complex`, `Rational`, and more. The library also provides advanced features such as extended JSON object creation, custom generators, and parser configurations. This README provides an overview of usage, advanced options, compatible Ruby types, and important notes for developers who want to integrate JSON handling seamlessly in their Ruby applications. --- ## Features - Encode and decode JSON data reliably - Support for core Ruby types and standard library extensions: - Core classes: `Time`, `Date`, `DateTime`, `Range`, `Struct`, `Regexp` - Standard library classes: `Complex`, `Rational`, `BigDecimal`, `Set`, `OpenStruct` - Extended JSON: serialize and deserialize custom Ruby objects using `json_class` - Custom JSON coders with configurable options - Fine control of parser and generator behaviors (encoding, error handling, indentation, circular reference checking) - Support for strict and non-strict JSON generation modes - Allows customization for ASCII-only output or UTF-8 with escapes - Support for frozen string optimization and symbolized keys on decode - Safe loading with deprecated support for legacy `create_additions` - Extensive test suite ensuring correctness and compatibility in multiple scenarios --- ## Installation This library is typically part of the Ruby standard library. You can use it directly without further installation: ```ruby require 'json' ``` To use additional JSON extensions, require their files: ```ruby require 'json/add/core' require 'json/add/complex' require 'json/add/rational' require 'json/add/bigdecimal' # if you use BigDecimal require 'json/add/ostruct' # if you use OpenStruct require 'json/add/set' # if you use Set ``` --- ## Usage ### Basic Encoding and Decoding ```ruby require 'json' # Encoding Ruby objects to JSON strings hash = { name: "Alice", age: 30, interests: ["Reading", "Hiking"] } json_string = JSON.generate(hash) puts json_string # => {"name":"Alice","age":30,"interests":["Reading","Hiking"]} # Decoding JSON strings to Ruby objects parsed_hash = JSON.parse(json_string) puts parsed_hash["name"] # => Alice ``` You can also use the shorthand indexed calls: ```ruby json_string = JSON[hash] # same as JSON.generate(hash) parsed_hash = JSON[json_string] # same as JSON.parse(json_string) ``` --- ### Extended JSON - Serializing Custom Ruby Objects To serialize and deserialize custom Ruby objects, define `to_json` and `json_create` methods: ```ruby class MyClass attr_reader :attr def initialize(attr) @attr = attr end def to_json(*args) { JSON.create_id => self.class.name, 'args' => [@attr] }.to_json(*args) end def self.json_create(object) new(*object['args']) end end obj = MyClass.new(123) json = JSON.generate(obj) obj2 = JSON.parse(json, create_additions: true) puts obj2.is_a?(MyClass) # => true puts obj2.attr # => 123 ``` If `create_additions` is disabled, the parsed JSON will be a Hash instead of your object: ```ruby obj_hash = JSON.parse(json, create_additions: false) puts obj_hash # => {"json_class"=>"MyClass", "args"=>[123]} ``` --- ### Handling Special Ruby Types To handle special types, require the corresponding files: ```ruby require 'json/add/complex' # Support Complex numbers require 'json/add/rational' # Support Rational numbers require 'json/add/bigdecimal' # Support BigDecimal numbers require 'json/add/ostruct' # Support OpenStruct objects require 'json/add/set' # Support Set collections ``` Example with `Rational`: ```ruby require 'json/add/rational' r = Rational(2, 3) json = JSON.generate(r) r2 = JSON.parse(json, create_additions: true) puts r2 == r # => true ``` --- ### JSON Coders with Custom Behaviors You can create custom JSON encoder/decoder instances using `JSON::Coder`: ```ruby coder = JSON::Coder.new(symbolize_names: true) do |object| # Custom dump implementation or fallback return value object.to_s end json = coder.dump({ "a" => 1 }) obj = coder.load(json) puts obj # => {:a=>1} ``` --- ### Parsing Options You can configure JSON parsing options: - `symbolize_names: true` to convert JSON keys to Ruby symbols - `create_additions: true` to create Ruby objects from extended JSON (`json_class`) - `allow_nan: true` to allow NaN and Infinity values during parsing - `allow_trailing_comma: true` to support dangling commas in arrays and objects - `freeze: true` freezes strings and arrays on creation to save memory Example: ```ruby json = '{"foo": "bar"}' parsed = JSON.parse(json, symbolize_names: true) puts parsed[:foo] # => "bar" ``` --- ### Generating Options Generate JSON with formatting options using: ```ruby options = { ascii_only: true, # Escape non-ASCII characters indent: ' ', # Indentation string space: ' ', # Space after colon space_before: '', # Space before colon object_nl: "\n", # Newline after object elements array_nl: "\n", # Newline after array elements max_nesting: 100, # Max depth for nested structures allow_nan: false, # Allow NaN, Infinity strict: false, # Strict JSON generation script_safe: false # Escape script-breaking characters } json_pretty = JSON.generate(obj, options) ``` Use `JSON.pretty_generate(obj)` for a standard pretty-printed output. --- ### Working with Strings and Encodings The library handles various string encodings robustly, supporting UTF-8, UTF-16, UTF-32, and ASCII-8BIT binary data conversions transparently. To generate ASCII-only JSON encoding, use: ```ruby json = JSON.generate("© ≠ €!", ascii_only: true) # => "\"\\u00a9 \\u2260 \\u20ac!\"" ``` --- ### Error Handling - `JSON::ParserError` is raised for malformed or invalid JSON inputs. - `JSON::GeneratorError` is raised for unsupported serialization cases, invalid encodings, or circular references exceeding max nesting. - `JSON::NestingError` is raised when the maximum allowed nesting depth is exceeded during parsing or generation. --- ### Thread Safety and Performance - Supports safe use with Ruby's Ractor and multiprocessing (tested on fork). - Options or states passed for JSON generation are immutable during the operation. - Implements circular reference detection in nested objects to prevent stack overflows. --- ### Deprecated Features - Legacy `JSON.load` with `create_additions` has been deprecated in favor of safer APIs such as `JSON.unsafe_load`. --- ## Testing The library includes an extensive test suite covering: - Core parsing and generation of various JSON structures - Extended JSON support for custom classes and Ruby standard classes - Support for multiple string encodings and edge cases - Parser error messages and robustness tests with malformed data fixtures - Custom JSON coders and generator states - Compatibility with various Ruby features like OpenStruct, BigDecimal, Set - Ractor and multi-process safety Run the test suite with Ruby's built-in `Test::Unit`: ```shell ruby -Ilib:test test/json/json_parser_test.rb ``` Or use your preferred Ruby test runner for all tests. --- ## Contributing Bug reports and pull requests are welcome. Please ensure tests pass and adhere to the established test coverage when adding features or fixing bugs. --- ## License [Specify your license here, if applicable.] --- ## Summary The JSON Ruby library is a mature and highly capable JSON serialization and deserialization tool that elegantly handles Ruby's object model and common data structures. It offers advanced configuration and robust error handling, suitable for a wide range of applications needing JSON processing in Ruby. Explore the tests and documentation to leverage all capabilities and integrate seamlessly into your Ruby projects.