【问题标题】:Can't store array in json field in postgresql (rails) can't cast Array to json无法在postgresql(rails)的json字段中存储数组无法将数组转换为json
【发布时间】:2013-06-29 21:50:27
【问题描述】:

这是我在运行 db:migrate 时遇到的错误

rake aborted!
can't cast Array to json

这是我的桌子

  class CreateTrips < ActiveRecord::Migration

          def change
            create_table :trips do |t|

              t.json :flights
              t.timestamps
            end
          end 
        end

这是在我的seeds.rb 文件中

flights = [{
    depart_time_hour: 600,
    arrive_time_hour: 700,

    passengers: [
        {
            user_id: 1,
            request: true    
        }
    ]
}]

trip = Trip.create(
  {
    name: 'Flight',

    flights: flights.to_json 
  }
)

由于某种原因,我不能这样做。如果我这样做。

trip = Trip.create(
      {
        name: 'Flight',
        flights: { flights: flights.to_json }
      }
    )

它有效。不过我不想要这个,因为现在我必须使用trip.flights.flights 访问json 数组。不是我想要的行为。

【问题讨论】:

  • 你应该正确抄写成功案例吗?我在flights: flights: ... 上遇到语法错误。你的意思是flights: {flights: ...
  • 嘿,是的,对不起。我改了。

标签: ruby-on-rails ruby ruby-on-rails-4 postgresql-9.2 rails-postgresql


【解决方案1】:

执行摘要:这是一个已知的issue,并在此pull request 中解决,在撰写本文时它正在等待合并。

长版:

嗯,我可以根据 Array/Hash 了解失败/成功的原因和方式。这是进行类型转换的 Rails 方法(来自 quoting.rb),它显然不支持从 Ruby Array 转换为 Postgres json,但它支持从 Hash 转换。另外,我在此方法的开头放置了一些调试代码,发现使用flightsflights.to_json 作为值并不重要,因为后者会转换为前者以进行此转换。我将做更多的挖掘工作,因为使用 psql 将 flights.to_json 的值插入到 json 列中没有问题。

    def type_cast(value, column, array_member = false)
      return super(value, column) unless column

      case value
      when Range
        return super(value, column) unless /range$/ =~ column.sql_type
        PostgreSQLColumn.range_to_string(value)
      when NilClass
        if column.array && array_member
          'NULL'
        elsif column.array
          value
        else
          super(value, column)
        end
      when Array
        case column.sql_type
        when 'point' then PostgreSQLColumn.point_to_string(value)
        else
          return super(value, column) unless column.array
          PostgreSQLColumn.array_to_string(value, column, self)
        end
      when String
        return super(value, column) unless 'bytea' == column.sql_type
        { :value => value, :format => 1 }
      when Hash
        case column.sql_type
        when 'hstore' then PostgreSQLColumn.hstore_to_string(value)
        when 'json' then PostgreSQLColumn.json_to_string(value)
        else super(value, column)
        end
      when IPAddr
        return super(value, column) unless ['inet','cidr'].include? column.sql_type
        PostgreSQLColumn.cidr_to_string(value)
      else
        super(value, column)
      end
    end

我继续在Array 案例中添加以下行:

        when 'json' then PostgreSQLColumn.json_to_string(value)

然后将 PostgreSQLColumn.json_to_string(在 cast.rb 中)更改为对 ArrayHash 类型的参数进行操作,我能够让您的用例通过。

目前我还没有检查是否有任何问题或拉取请求

顺便说一句,我假设您知道您可以通过使用 text 字段而不是 json 字段来解决此问题。 json 为您提供的唯一我知道的是否是数据库级别的验证。如果您认为这很重要,我很想知道为什么,因为我正在开发的网络应用程序中有一些带有 json 内容的文本字段,我想知道转换它们的好处(如果有的话) .

【讨论】:

  • JSON 数据类型会随着它的成熟和更多的功能上线使用它而变得更加有用。你现在不能用它做很多事情,但是会有一些函数用于查看 JSON 内部(类似于当前的 hstore 函数);它也很适合 pl/v8 程序(Rails 愚蠢地对此不屑一顾)。尽管 Rails 想将数据库视为一个愚蠢的电子表格,但不要低估让数据库检查数据的一致性和完整性的实用性。
猜你喜欢
  • 1970-01-01
  • 2016-07-25
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 2020-10-01
相关资源
最近更新 更多