Frederick John
Frederick John

Reputation: 527

Accessing Values in Deeply Nested Array - Ruby on Rails

I am using an API call which returns a JSON response. I want to access the data inside the response so I can create some nice display cards showing the info and pictures. Here is a snippet from the response, the response property is populated with about 20 objects I'll include just two for brevity:

{
    "success": true,
    "message": "",
    "result": [
        {
            "MarketCurrency": "LTC",
            "BaseCurrency": "BTC",
            "MarketCurrencyLong": "Litecoin",
            "BaseCurrencyLong": "Bitcoin",
            "MinTradeSize": 1e-8,
            "MarketName": "BTC-LTC",
            "IsActive": true,
            "Created": "2014-02-13T00:00:00",
            "Notice": null,
            "IsSponsored": null,
            "LogoUrl": "https://i.imgur.com/R29q3dD.png"
        },
        {
            "MarketCurrency": "DOGE",
            "BaseCurrency": "BTC",
            "MarketCurrencyLong": "Dogecoin",
            "BaseCurrencyLong": "Bitcoin",
            "MinTradeSize": 1e-8,
            "MarketName": "BTC-DOGE",
            "IsActive": true,
            "Created": "2014-02-13T00:00:00",
            "Notice": null,
            "IsSponsored": null,
            "LogoUrl": "https://i.imgur.com/e1RS4Hn.png"
        },

In my Rails controller I'm using JSON.parse and I'm trying to turn it into an object with the Open struct option:

@markets = JSON.parse(markets.to_json, object_class: OpenStruct)

In my view I'll do this <%[email protected]%> and it shows Array and not object. So I try this <%[email protected]%> and it shows 1. If I do <%=@markets[0]['success']%> I would expect it to return true but it returns 'success'. So, I'm not understanding why the ostruct library isn't working like I would expect or how I can get to the objects stored in the result array. Any help is greatly appreciated!

Upvotes: 0

Views: 630

Answers (2)

Frederick John
Frederick John

Reputation: 527

After much debugging and some assistance, I was able to get it to work. The response from the API call was an array with one item. The item was a long string of the entire dataset.

In order to get the expected behavior of "true" when calling @markets.success, I first had to

raw_markets = JSON.parse(markets.to_json)

followed by

@markets = raw_markets.map do |market|
      JSON.parse(market, object_class: OpenStruct)

Note: the variable markets holds the original api call:

markets = open('url-to-api')

After this I would get @markets.success = "true" and @markets.result[0] held the first result, @markets.result[1] held the second result, and so on.

Upvotes: 1

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33420

You already have a JSON response, isn't needed to use to_json again, try just parsing that object, and then use the dot . to access its fields, as an OpenStruct object now then you can access them as methods:

require 'json'

a = '{
  "success": true,
  "message": "",
  "result": [{
    "MarketCurrency": "LTC",
    "BaseCurrency": "BTC",
    "MarketCurrencyLong": "Litecoin",
    "BaseCurrencyLong": "Bitcoin",
    "MinTradeSize": 1e-8,
    "MarketName": "BTC-LTC",
    "IsActive": true,
    "Created": "2014-02-13T00:00:00",
    "Notice": null,
    "IsSponsored": null,
    "LogoUrl": "https://i.imgur.com/R29q3dD.png"
  }, {
    "MarketCurrency": "DOGE",
    "BaseCurrency": "BTC",
    "MarketCurrencyLong": "Dogecoin",
    "BaseCurrencyLong": "Bitcoin",
    "MinTradeSize": 1e-8,
    "MarketName": "BTC-DOGE",
    "IsActive": true,
    "Created": "2014-02-13T00:00:00",
    "Notice": null,
    "IsSponsored": null,
    "LogoUrl": "https://i.imgur.com/e1RS4Hn.png"
  }]
}'

b = JSON.parse(a, object_class: OpenStruct)
p b.success
# => true

Upvotes: 2

Related Questions