如何使用Ruby on Rails解析JSON?

时间:2009-12-01 14:58:02

标签: ruby-on-rails ruby json

我正在寻找一种简单的方法来解析JSON,提取一个值并将其写入Rails中的数据库。

特别是我正在寻找的是一种从bit.ly API返回的JSON中提取shortUrl的方法:

{
  "errorCode": 0,
  "errorMessage": "",
  "results":
  {
    "http://www.foo.com":
    {
       "hash": "e5TEd",
       "shortKeywordUrl": "",
       "shortUrl": "http://bit.ly/1a0p8G",
       "userHash": "1a0p8G"
    }
  },
  "statusCode": "OK"
}

然后使用shortUrl并将其写入与长URL关联的ActiveRecord对象。

这是我完全可以在概念中思考的事情之一,当我坐下来执行时,我意识到我有很多需要学习的东西。

12 个答案:

答案 0 :(得分:438)

这些答案有点过时了。所以我给你:

hash = JSON.parse string

Rails应该为您自动加载json模块,因此需要添加require 'json'

答案 1 :(得分:184)

在Rails中解析JSON非常简单:

parsed_json = ActiveSupport::JSON.decode(your_json_string)

假设您想要将shortUrl与之关联的对象是一个Site对象,它有两个属性 - short_url和long_url。要获得shortUrl并将其与相应的Site对象相关联,您可以执行以下操作:

parsed_json["results"].each do |longUrl, convertedUrl|
  site = Site.find_by_long_url(longUrl)
  site.short_url = convertedUrl["shortUrl"]
  site.save
end

答案 2 :(得分:56)

这个答案很老了。 pguardiario得到了它。

要查看的网站是JSON implementation for Ruby。这个站点提供了一个可以为更快的C扩展变体安装的gem。

根据documentation page给出的基准,他们声称 21.500x ActiveSupport::JSON.decode

代码与Milan Novota对这个gem的答案相同,但解析只是:

parsed_json = JSON(your_json_string)

答案 3 :(得分:19)

以下是2013年的更新。

红宝石

Ruby 1.9有一个带有C扩展名的默认JSON gem。您可以将其与

一起使用
require 'json'
JSON.parse ''{ "x": "y" }'
# => {"x"=>"y"}

parse!变体可用于安全来源。还有其他宝石,可能比默认实现更快。有关列表,请参阅multi_json

滑轨

Rails的现代版本使用multi_json,这是一个自动使用最快的JSON gem的gem。因此,推荐的方法是使用

object = ActiveSupport::JSON.decode json_string

有关详细信息,请参阅ActiveSupport::JSON。特别是,方法源中的重要一行是

data = MultiJson.load(json, options)

然后在您的Gemfile中,包含您要使用的gem。例如,

group :production do
  gem 'oj'
end

答案 4 :(得分:7)

Ruby捆绑的JSON能够独立展示一些魔力。

如果您有一个包含要解析的JSON序列化数据的字符串:

JSON[string_to_parse]

JSON将查看该参数,看它是一个字符串并尝试解码。

同样,如果您想要序列化的哈希或数组,请使用:

JSON[array_of_values]

或者:

JSON[hash_of_values]

JSON将序列化它。如果您想避免to_json的视觉相似性,也可以使用[] method方法。

以下是一些例子:

hash_of_values = {'foo' => 1, 'bar' => 2}
array_of_values = [hash_of_values]

JSON[hash_of_values] 
# => "{\"foo\":1,\"bar\":2}"

JSON[array_of_values] 
# => "[{\"foo\":1,\"bar\":2}]"

string_to_parse = array_of_values.to_json
JSON[string_to_parse]
# => [{"foo"=>1, "bar"=>2}]

如果您在JSON中使用,您可能会注意到它是YAML的一个子集,实际上YAML解析器正在处理JSON。你也可以这样做:

require 'yaml'

YAML.load(string_to_parse)
# => [{"foo"=>1, "bar"=>2}]

如果您的应用正在解析YAML和JSON,您可以让YAML处理两种类型的序列化数据。

答案 5 :(得分:5)

require 'json'
out=JSON.parse(input)

这将返回一个哈希

答案 6 :(得分:5)

import {Component, Input, DynamicComponentLoader, ElementRef, AfterViewInit} from 'angular2/core';

@Component({
  selector: 'celestial-object',
  template: `
    <span #loadSpecificCelestialObjectHere></span>
  `
})

export class CelestialObject implements AfterViewInit {
  @Input() descriptor: any;

  constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) { /* */ }

  ngAfterViewInit() {
    this.dcl.loadIntoLocation(descriptor.type, this.elementRef, 'loadSpecificCelestialObjectHere').then((comp) => {
      comp.instance.descriptor = this.descriptor;
    });
  }
}

使用哈希并执行您想要执行的操作。

答案 7 :(得分:2)

RUBY区分大小写。

require 'json' # json must be lower case

JSON.parse(<json object>)  

例如

JSON.parse(response.body) # JSON must be all upper-case

答案 8 :(得分:2)

Oj gem(https://github.com/ohler55/oj)应该有效。它简单快捷。

http://www.ohler.com/oj/#Simple_JSON_Writing_and_Parsing_Example

require 'oj'

h = { 'one' => 1, 'array' => [ true, false ] }
json = Oj.dump(h)

# json =
# {
#   "one":1,
#   "array":[
#     true,
#     false
#   ]
# }

h2 = Oj.load(json)
puts "Same? #{h == h2}"
# true

Oj gem不会为JRuby工作。对于JRuby,这个(https://github.com/ralfstx/minimal-json)或者这个(https://github.com/clojure/data.json)可能是不错的选择。

答案 9 :(得分:2)

这就是我要做的事情:

json = "{\"errorCode\":0,\"errorMessage\":\"\",\"results\":{\"http://www.foo.com\":{\"hash\":\"e5TEd\",\"shortKeywordUrl\":\"\",\"shortUrl\":\"http://b.i.t.ly/1a0p8G\",\"userHash\":\"1a0p8G\"}},\"statusCode\":\"OK\"}"

hash = JSON.parse(json)
results = hash[:results]

如果您知道源网址,则可以使用:

source_url = "http://www.foo.com".to_sym

results.fetch(source_url)[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

如果您不知道源网址的密钥,则可以执行以下操作:

results.fetch(results.keys[0])[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

如果您不想使用符号查找密钥,可以将哈希中的密钥转换为字符串:

results = json[:results].stringify_keys

results.fetch(results.keys[0])["shortUrl"]
=> "http://b.i.t.ly/1a0p8G"

如果您担心JSON结构可能会发生变化,您可以在尝试访问密钥之前构建一个简单的JSON模式并验证JSON。这将提供一名警卫。

注意:由于发布规则,不得不破坏bit.ly网址。

答案 10 :(得分:2)

这可以如下完成,只需要使用JSON.parse,然后您可以使用索引正常遍历它。

#ideally not really needed, but in case if JSON.parse is not identifiable in your module  
require 'json'

#Assuming data from bitly api is stored in json_data here

json_data = '{
  "errorCode": 0,
  "errorMessage": "",
  "results":
  {
    "http://www.foo.com":
    {
       "hash": "e5TEd",
       "shortKeywordUrl": "",
       "shortUrl": "http://whateverurl",
       "userHash": "1a0p8G"
    }
  },
  "statusCode": "OK"
}'

final_data = JSON.parse(json_data)
puts final_data["results"]["http://www.foo.com"]["shortUrl"]

答案 11 :(得分:-3)

您可以尝试这样的事情:

def details_to_json
{
  :id                    => self.id, 
  :credit_period_type    => self.credit_period_type,
  :credit_payment_period => self.credit_payment_period,

 }.to_json
end