Open-source project
rails/jbuilder avatar
rails/jbuilder

Jbuilder turns JSON views into Ruby you can actually read

Jbuilder: generate JSON objects with a Builder-style DSL

4,419 stars456 forksRubyMIT

At a glance

What is it?
A small MIT-licensed gem that lives in the rails org and gives Rails a builder-style DSL for JSON templates, with partials, top level arrays, and a 2.15 release line from May 2026.
Who is it for?
Jbuilder earns its place in any Rails app that renders JSON from a view template, because the DSL removes the nested-hash indentation that makes serializers hard to review and impossible to read in a diff. The four methods worth learning cold are `array!`, `partial!`, `merge!` and `set!`, and once those are in your hands the rest of the README is reference material.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 159 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • rails/jbuilder4,419 ★ · -2
Star history
Repository2026-10-072026-11-07
rails/jbuilder4.4k4.4k

-2 Stars in the last 31 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The problem is indentation, not JSON

The README states the motivation plainly: Jbuilder gives you a simple DSL for declaring JSON structures that beats manipulating giant hash structures, and that this helps most when the generation process is full of conditionals and loops. That is the whole pitch. Building JSON in Ruby usually means nesting hashes and then reading indentation to figure out what shape the response has, which is exactly the situation where a conditional for an admin-only field turns into a brace-counting exercise.

A view template in Jbuilder looks like this, taken straight from the README:

ruby
json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)

json.author do
  json.name @message.creator.name.familiar
  json.email_address @message.creator.email_address_with_name
  json.url url_for(@message.creator, format: :json)
end

if current_user.admin?
  json.visitors calculate_visitors(@message)
end

json.comments @message.comments, :content, :created_at

The `if` reads like the `if` you already write in an ERB or Haml template, and the block form for nested objects means the shape is decided by indentation rather than by punctuation. The README shows the resulting structure side by side, which is useful because it confirms the mapping is direct: a block becomes a nested object, an array argument becomes an array, and no transformation happens behind your back.

What the library does not do is reduce the JSON. There is no schema, no type coercion and no validation. It is a template language for JSON, and treating it as a serializer would be a category error.

Top level arrays are the case most serializers get wrong

Most of the DSL is about building objects, but the case that trips up hand-rolled serializers is a collection endpoint, where the top level of the response is an array rather than an object. Jbuilder handles it directly with `array!`, and the README documents both a block form that yields each element and a shorthand that extracts attributes:

ruby
json.array! @comments do |comment|
  next if comment.marked_as_spam_by?(current_user)

  json.body comment.body
  json.author do
    json.first_name comment.author.first_name
    json.last_name comment.author.last_name
  end
end

json.array! @people, :id, :name

The `next if` line is worth pausing on. Skipping an element inside the block is the filtering idiom, and it is the reason the block form exists: you can express visibility rules per element without building an intermediate array first. The attribute-shorthand form skips the block entirely and is the readable equivalent of `map(&:attributes)`, restricted to the columns you name.

There is a related case for arrays of objects without a collection: `child!`, which appends one element at a time under the current key. The README's `json.people` example nests two `json.child!` blocks and produces an array of two objects. If you find yourself reaching for it, a plain Ruby array passed to `json.people` is usually clearer when the data is static.

Partials are where the design pays for itself

The partial support is the strongest argument for adopting Jbuilder in a Rails app with more than one JSON endpoint, because it lets an object's JSON live in one file instead of being duplicated per view. The base call passes locals explicitly:

ruby
json.partial! 'comments/comments', comments: @message.comments

json.post @post, partial: 'posts/post', as: :post

json.array! @posts, partial: 'posts/post', as: :post

json.comments @post.comments, partial: 'comments/comment', as: :comment

The `as:` option names the local variable inside the partial, and the README spells out the semantics: when the value is a collection, each element is passed under that name; when it is a singular object, the object itself is. Extra locals can be passed alongside, as the README shows with `include_body: true` and `include_author: true`.

The README also warns against reading `as:` as nesting. `json.partial! @comment, as: :comment` inlines the attributes of the object, while wrapping it in a `json.comment do` block with a path string nests them under a `comment` property. Those two produce different JSON, and the difference is a common source of client-side confusion.

Composing Jbuilder objects outside of Rails

The gem is usable stand-alone, not only as an ActionView template handler. The README's composition example wraps a Jbuilder in a plain Ruby class and nests one inside another, which is a lightweight alternative to writing a serializer object per resource:

ruby
class Company
  # ... Class Definition ... #
  def to_builder
    Jbuilder.new do |company|
      company.name name
      company.president president.to_builder
    end
  end
end

company.to_builder.target!

The `to_builder` convention plus `target!` gives you a reusable definition that a view can render under a key. The tradeoff is real: once a resource's JSON lives in a Ruby class, it is no longer obvious from a template which fields an endpoint exposes, and you need tests to catch a field disappearing. Inside a Rails app, the view is usually the better home. Outside one, or when the same shape is needed by a background job and a controller, the object form earns its keep.

For runtime flexibility the README offers `set!` for dynamic key names and `merge!` for folding in an existing hash or array, so a builder can absorb a precomputed structure without losing its nesting.

What 2.15 actually changed

The release history shows v2.15.0 published 2026-05-15 and v2.15.1 published 2026-05-26, following v2.14.1 from 2025-08-12.

A small gem with an unusually broad search footprint

Two things about the repository itself are worth setting down. First, this is not a community fork: it lives under the `rails` GitHub organization, ships an MIT license as `MIT-LICENSE`, and its gemspec is `jbuilder.gemspec`.

Second, the repository carries no homepage field and no documentation site. The README is the whole manual, and it is organized as a feature tour rather than a reference, so a few behaviours are only described in prose. The tree is correspondingly small: `lib/`, `test/`, `gemfiles/`, `Appraisals` for testing against multiple dependency sets, `bin/`, and `.github/` for workflows. There is no `doc/` directory and no separate guides, which means questions about edge-case rendering behaviour end up in issues rather than in docs.

The repository was last pushed on 2026-06-01 and is not archived, so the maintenance question is settled: the gem is still being worked on.

Editorial conclusion

Jbuilder earns its place in any Rails app that renders JSON from a view template, because the DSL removes the nested-hash indentation that makes serializers hard to review and impossible to read in a diff. The four methods worth learning cold are `array!`, `partial!`, `merge!` and `set!`, and once those are in your hands the rest of the README is reference material. Start by converting one existing `.json.jbuilder` view rather than rewriting a whole API surface, and note that the repository reports no project homepage, so the README and the gemspec are the only documentation the project itself carries.

Frequently asked questions

Is Jbuilder still maintained?

The repository is not archived and was last pushed on 2026-06-01. Releases landed in May 2026 with v2.15.0 and v2.15.1.

How do I return a top level JSON array from a Rails view?

Use `json.array!` at the top of the template, either with a block that yields each element or with an attribute list such as `json.array! @people, :id, :name`. The README shows a `next if` guard inside the block for skipping individual elements.

What is the difference between `as:` and nesting a Jbuilder partial?

`as:` names the local variable the partial receives and does not add a wrapper key, so `json.partial! @comment, as: :comment` inlines the object's attributes. Wrapping the call in a `json.comment do` block with an explicit path nests those attributes under a `comment` property instead.

Does Jbuilder work outside of Rails?

Yes. The README documents using it stand-alone, including the `to_builder` convention where a class returns a `Jbuilder.new` block that another builder nests as a value, then materializes with `target!`. In a Rails app the view is usually the better home for the same shape.

Official sources

  1. Issues
  2. License: MIT
  3. rails/jbuilder on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rails-jbuilder.svg)](https://hysenlabs.com/projects/rails-jbuilder)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/rails-jbuilder.svg)](https://hysenlabs.com/projects/rails-jbuilder)

Was this useful?