Skip to content

Instantly share code, notes, and snippets.

@peterc
Last active November 7, 2024 21:22
Show Gist options
  • Save peterc/8ac6f82f5d5b18622189fcfc7f41b6fd to your computer and use it in GitHub Desktop.
Save peterc/8ac6f82f5d5b18622189fcfc7f41b6fd to your computer and use it in GitHub Desktop.
LLM generated documentation for Ruby's "json" gem

A test of the technique illustrated by Simon Willison at https://til.simonwillison.net/llms/docs-from-tests

JSON Library Usage Documentation

Basic Usage

Parsing JSON

# Parse JSON string into Ruby objects
JSON.parse('{"name": "John", "age": 30}')  # => {"name"=>"John", "age"=>30}

# Parse JSON array
JSON.parse('[1, 2, 3]')  # => [1, 2, 3]

# Parse from IO objects
File.open('data.json') do |file|
  JSON.parse(file.read)
end

Generating JSON

# Generate JSON from Ruby objects
JSON.generate({name: "John", age: 30})  # => '{"name":"John","age":30}'

# Alternative syntax using #to_json
{name: "John", age: 30}.to_json  # => '{"name":"John","age":30}'

# Pretty print JSON with nice formatting
JSON.pretty_generate({name: "John", age: 30})
# {
#   "name": "John",
#   "age": 30
# }

Advanced Options

Parsing Options

# Symbolize names (keys become symbols)
JSON.parse('{"name": "John"}', symbolize_names: true)  # => {:name=>"John"}

# Allow NaN, Infinity in JSON
JSON.parse('{"value": NaN}', allow_nan: true)

# Set maximum nesting depth
JSON.parse(json, max_nesting: 100)  # Raises error if nesting > 100

# Allow trailing commas in arrays/objects
JSON.parse('[1,2,3,]', allow_trailing_comma: true)  # => [1,2,3]

# Parse numeric values as BigDecimal
JSON.parse('{"price": 9.99}', decimal_class: BigDecimal)

Generation Options

# ASCII encode all non-ASCII characters
JSON.generate(data, ascii_only: true)

# Control spacing and indentation
JSON.generate(data, space: '  ', indent: '  ')

# Allow NaN/Infinity in output
JSON.generate(data, allow_nan: true)

# Escape forward slashes
JSON.generate(data, escape_slash: true)

# Make output safe for all JavaScript engines
JSON.generate(data, script_safe: true)

Working with Custom Objects

class Person
  def initialize(name)
    @name = name
  end
  
  # Define how object should be serialized to JSON
  def to_json(*args)
    {
      'json_class' => self.class.name,
      'name' => @name
    }.to_json(*args)
  end
  
  # Define how to create object from JSON
  def self.json_create(hash)
    new(hash['name'])
  end
end

# Usage
person = Person.new("John")
json = person.to_json
parsed = JSON.parse(json, create_additions: true)  # Creates Person object

Error Handling

begin
  JSON.parse(invalid_json)
rescue JSON::ParserError => e 
  puts "Invalid JSON: #{e.message}"
end

begin
  JSON.generate(invalid_object) 
rescue JSON::GeneratorError => e
  puts "Cannot generate JSON: #{e.message}" 
end

Best Practices

  1. Always use exception handling when parsing untrusted JSON input

  2. Use JSON.parse with symbolize_names: true when working with symbol keys

  3. Use JSON.pretty_generate for human-readable output

  4. Set appropriate max_nesting limits when parsing untrusted data

  5. Use create_additions: true carefully as it can execute arbitrary code

  6. Consider using decimal_class: BigDecimal when precision is important

  7. Test JSON generation/parsing with various character encodings

This documentation covers the main functionality of the JSON library based on the test files. The library provides many additional options and features that can be found in the source code and official documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment