# crack is two parsers packaged as one small Ruby gem

> crack is a Ruby library that does exactly two things: parse XML and parse JSON. The parsers were taken from Merb and Rails and repackaged as a standalone gem, with the deliberate property that you can require only the half you need. The whole public surface is four require lines and two parse methods.

**jnunemaker/crack** — Really simple JSON and XML parsing, ripped from Merb and Rails.

- Repository: https://github.com/jnunemaker/crack
- Stars: 551 · Forks: 93
- Language: Ruby
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/jnunemaker-crack

## Two parsers, no more

The description of the gem is short and does not oversell anything. Really simple JSON and XML parsing, ripped from Merb and Rails.

The provenance matters more than it might seem, and the author is explicit about it. The XML parser is ripped from Merb and the JSON parser is ripped from Rails, and the statement about credit is unusually direct: I take no credit, just packaged them for all to enjoy and easily use.

So this is a packaging project rather than a parsing project. Both parsers existed and worked inside larger frameworks, and the argument for extracting them is that they were useful on their own. A Merb application did not need to load a Merb application to parse XML, and a Rails application did not need to load Rails to parse JSON, and the people who wrote them had already done the work of making them small and dependable.

That is a genuinely useful contribution and it is also a modest one, and being clear about which is which is the right posture for a library like this.

The naming follows from the source. Merb's XML parsing lived in a module called Crack, and the gem keeps that name, which is why the methods are called as Crack::XML.parse and Crack::JSON.parse rather than something more descriptive.

The copyright notice is 2009 John Nunemaker, and the project is MIT licensed with the details in the LICENSE file. The repository layout is minimal in the way the gem is: a Gemfile, a History file, a Rakefile, a crack.gemspec, a lib/ directory, a script/ directory and a test/ directory, plus the .github directory for the workflows.

The presence of a script/ directory is worth noting, because it is where a gem puts its executables. For a library with no command line interface that directory is either empty of real entries or holds development helpers, and it tells you the gem is meant to be required from application code rather than run.

## Four requires, and the reason for the split

The usage section is the entire public interface of the gem, and it is four lines.

```ruby
gem 'crack' # in Gemfile
require 'crack' # for xml and json
require 'crack/json' # for just json
require 'crack/xml' # for just xml
```

The first line is the Gemfile entry. The second requires crack for both xml and json. The third requires crack/json for just json, and the fourth requires crack/xml for just xml.

That third and fourth line are the design point. Most people would write a single require and load everything, and for a gem that is fine because the whole thing is small. But crack came out of frameworks where the parsers were separate concerns, and keeping them separately requirable costs nothing while letting a program that only reads JSON avoid pulling in an XML parser and its dependencies.

The library and framework origins also explain the naming convention inside the gem. Both parsers live under the Crack namespace, one as Crack::XML and one as Crack::JSON, so the format is part of the constant path rather than an argument. That is a difference from the more common style where you would have a single Parsers module and a format argument, and it is the style both Merb and Rails happened to use in the code that was extracted.

For a caller the practical difference is that you end up with either Crack::JSON.parse or Crack::XML.parse in your code, and the compiler of your eye has to keep track of which namespace is which. The examples make that clear.

The gem's own dependency situation follows from the extraction too. There is no mention of Rails or Merb as dependencies, and the gemspec sits alongside a plain Gemfile, so what you get is the parsing code itself rather than the frameworks it came from.

## Plain hashes come out, whatever goes in

The examples are two lines each, and they show the convention that matters most about the library.

```ruby
Crack::XML.parse("<tag>This is the contents</tag>")
# => {'tag' => 'This is the contents'}

Crack::JSON.parse('{"tag":"This is the contents"}')
# => {'tag' => 'This is the contents'}
```

Both parsers return a plain Ruby hash, with string keys and string values, and the XML case shows the tag name becoming the key and the text content becoming the value.

That last point is where XML parsing has a hundred different conventions and this one picks a simple one. A document with nested elements does not become a nested hash in this example, and an XML document with attributes has to encode them somehow. The library is not trying to give you a document object model, it is trying to give you the data, and the JSON parser obviously has no choice but to return a hash.

The consistency between the two is what makes the gem pleasant to use. You can switch a data source from JSON to XML without changing how you index the result, as long as the shape of the data matches. That is the practical reason the two parsers are packaged together in the first place.

The simplicity has a corresponding limitation, and it is worth being clear that the library does not attempt to be a general XML processor. It has no streaming interface, no schema validation, no XPath and no namespace handling. It parses and it hands you a hash.

For the cases the gem was written for, that is exactly right. A configuration file, an API response, a small XML document from a device, a payload you need to look at a couple of fields in: these are the situations where a full XML stack is overkill and where the thing you want is a hash you can index.

The error behaviour is the other thing the examples do not show, and that is a fair thing to check in the source and the tests before relying on it for input you do not control. Parsing malformed documents is where simple libraries differ most, and where the difference between a raised error and a nil result matters a lot to the calling code.

## A gem with a long history and an explicit contribution path

The compatibility list is broad and worth quoting in full: Ruby 2.x, Ruby 3.x and Ruby 4.x.

Supporting three major series of the language is unusual for a gem this small, and it is the kind of thing that happens when a library is stable enough that nobody needs to change it. There is no configuration to keep in step with the language and no dependency tree to fight with, so the gem keeps working across versions by not doing anything.

The version support also says something about the maintenance situation. The copyright is 2009 and there is a History file, which is the changelog convention for a long-lived Ruby library. The header carries three badges: a test workflow badge, a gem version badge from the RubyGems service, and a downloads badge. The downloads badge in particular is a nice touch for a library like this, since it is a measure of use rather than an opinion about quality.

The contribution section is short and prescriptive, and the order of the steps is the useful part.

Fork the project. Make your feature addition or bug fix. Add tests for it, and the stated reason is that this is important so I don't break it in a future version unintentionally. Run the tests with rake test. Open a pull request with the changes.

That third step is the one that distinguishes how this project is maintained. The request is not that you fix the bug but that you add a test for it, with an explicit explanation of why: to catch the case when a future Ruby version changes the behaviour that the test depends on. A library that only parses data has very few ways to break, and almost all of them come from the language or its standard library changing underneath it. Tests are the only defence against that, and the author says so.

The Rakefile is what makes rake test work, and the script/ directory and test/ directory are where the tests and the development helpers live.

## Where this fits against the standard library and against Rails

The comparison that matters is with what the standard library gives you, because Ruby has a JSON parser built in.

Ruby's own json library parses JSON into hashes, and it does it well. For JSON alone, using the standard library is the obvious choice, and crack offers no advantage there beyond the fact that the same call site would work for either format.

So the case for crack is XML, and the case for the JSON half is consistency. If your program has to read both, having one gem and one calling convention for both is worth something, and having the JSON parser be the same implementation the rest of the Ruby ecosystem has been using is a modest benefit in itself.

The comparison with Rails is more interesting, because crack's JSON parser is the one Rails uses. If your project already depends on Rails, then requiring crack/json gets you the same parser you already have, without pulling in the framework. The difference is that you no longer have to go through the Rails initialisation to use it, which matters in a script, a rake task or a small service that has no business loading a web framework.

The comparison with a full XML library such as Nokogiri is the opposite. Nokogiri gives you a document object model, XPath, namespaces and streaming, and it handles arbitrary XML properly. Crack gives you a hash. For a small, well-behaved document the hash is far more convenient, and for anything complicated the hash approach will lose you information.

So the honest summary is that this is a small, focused, well-packaged library with a clear job and a clear limit. It does not try to be a framework and it does not try to be a complete XML solution. It is two competent parsers from two mature projects, made available to people who need a parser and not the rest of the stack.

That is a perfectly good thing for a gem to be, and the repository's own framing, no credit taken and packaged for all to enjoy and easily use, matches that.

## Conclusion

Adopt crack if you want one small dependency that parses XML or JSON into plain Ruby hashes and nothing else, since the whole point of the gem is that it does not bring a web framework with it. Skip it if your project already depends on Rails, since the JSON parser is the one Rails uses, and if you need streaming, schema validation or error handling beyond what the parsers give you. Verify first which Ruby versions you need, since the compatibility list covers Ruby 2.x, 3.x and 4.x, that you require only the format you use, and that you read the History file before upgrading, since this is a small library that has been packaged for a long time.

## FAQ

### What is the crack Ruby gem?

It is really simple JSON and XML parsing, ripped from Merb and Rails. The XML parser is taken from Merb and the JSON parser from Rails, and the author states that he takes no credit, having packaged them for all to enjoy and easily use. Both live under the Crack namespace, as Crack::XML.parse and Crack::JSON.parse.

### How do I install and use crack?

Add `gem 'crack'` to your Gemfile, then require it. `require 'crack'` loads both the XML and JSON parsers, `require 'crack/json'` loads only the JSON one and `require 'crack/xml'` loads only the XML one. A parse returns a plain Ruby hash, for example Crack::XML.parse("<tag>This is the contents</tag>") returns a hash mapping the tag to its text.

### Which Ruby versions does crack support and how do I contribute?

The compatibility list covers Ruby 2.x, Ruby 3.x and Ruby 4.x. To contribute you fork the project, make your feature addition or bug fix, add tests for it so the behaviour is not broken unintentionally in a future version, run the tests with `rake test`, and open a pull request with the changes.

## Sources

- [Issues](https://github.com/jnunemaker/crack/issues)
- [jnunemaker/crack on GitHub](https://github.com/jnunemaker/crack)
- [License: MIT](https://github.com/jnunemaker/crack/blob/master/LICENSE)
- [README](https://github.com/jnunemaker/crack/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jnunemaker-crack
