Alex Treichler
Alex Treichler

Reputation: 21

'JSON.parse' error handling invalid/non JSON format

I request information from an HTTP streaming service. It provides data in JSON format. Here is the documentation. Here is a part of the code I am using:

require 'uri'
require 'net/https'
require 'json'


uri = URI("https://api.tradier.com/v1/markets/events/session")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
http.read_timeout = 30
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER

# Headers

request["Accept"] = "application/json"
request["Authorization"] = "Bearer xxx"

# Send synchronously

response = http.request(request)

# parses response

parse = JSON.parse(response.body)

#out puts values only from response

sessionid = parse.values[0]["sessionid"]
url = parse.values[0]["url"]


uri = URI("#{url}?sessionid=#{sessionid}&symbols=aapl")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
http.read_timeout = 30
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER

# Headers

request["Accept"] = "application/json"
request["Authorization"] = "Bearer xxx"


http.request request do |response|
  response.read_body do |data|
    puts data.class
  #  info = JSON.parse(data, :quirks_mode => true)
  #  puts info.values
    end
end

I want to have the system continue the program. It seems that I need to use begin and rescue, but I cannot get them to work. When I request data, I get the following error:

`parse': 757: unexpected token at '{"type":"trade","symbol":"AAPL","exch":"Q","price":"191.23","size":"1081622","cvol":"18308460","date":"1528747200000","last":"191.23"}{"type":"summary","symbol":"AAPL","open":"191.35","high":"191.97","low":"190.21","prevClose":"191.7","close":"191.23"}' (JSON::ParserError)

Upvotes: 0

Views: 127

Answers (1)

Kimmo Lehto
Kimmo Lehto

Reputation: 6041

The endpoint you are using is documented in Tradier API docs and it's a streaming endpoint.

It appears that the response is not chunked to contain just one JSON document per chunk. It however does appear that the documents are separated by linefeeds, making the response look like:

{ "json": "data" }
{ "more": "data" }

And that is not valid JSON. You probably need to parse them one by one by doing something like:

http.request request do |response|
  response.read_body do |data|
    data.each_line do |chunk|
      info = JSON.parse(chunk)
      puts info.inspect
    end
  end
end

If the response chunking happens in the middle of JSON documents, you must use some kind of buffered reader.

Upvotes: 2

Related Questions