json.object! do

record.attributes.each do |name, value|
  # Skip if attribute is included in excludes
  next if defined?(excludes) && excludes[record.model_name.singular.to_sym].try(:find) { |x| x.to_s == name.to_s }
  json.set! name, value
end

includes.each do |inc, subinc|
  next if ["limit", "offset", "order", "when", "where", "distinct", "distinct_on"].include?(inc)

  case association = record.class.reflect_on_association(inc)
  when ActiveRecord::Reflection::AbstractReflection
    if association.collection?
      can_cache = can_cache_relation?(record, inc, subinc)
      json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
        json.set! inc do
          partial = model_partial(association.klass)
          # TODO limit causes preloaded assocations to reload
          sub_records = record.send(inc)

          sub_records = sub_records.limit(subinc["limit"]) if subinc["limit"]
          sub_records = sub_records.offset(subinc["offset"]) if subinc["offset"]
          sub_records = sub_records.reorder(subinc["order"]) if subinc["order"]
          sub_records = sub_records.filter(subinc["where"]) if subinc["where"]
          sub_records = sub_records.distinct if subinc["distinct"]
          sub_records = sub_records.distinct_on(subinc["distinct_on"]) if subinc["distinct_on"]

          json.array! sub_records, partial: partial, as: partial.split("/").last, locals: { includes: subinc }
        end
      end
    else
      can_cache = can_cache_relation?(record, inc, subinc)
      if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
        can_cache = can_cache && !record.send(association.foreign_key).nil?
      end
      json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
        json.set! inc do
          value = record.send(inc)
          if value.nil?
            json.value! nil
          else
            partial = model_partial(value)
            json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
          end
        end
      end
    end
  else
    if record.respond_to?(inc)
      value = record.send(inc)
      if value.nil?
        json.set! inc, nil
      elsif value.is_a?(ActiveModel::Model)
        json.set! inc do
          partial = model_partial(value)
          json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
        end
      else
        json.set! inc, value.as_json
      end
    end
  end

end

if !record.errors.blank?
  errs = record.errors.to_hash
  errs.default_proc = nil
  json.set! "errors", errs
end

end