Home > Software engineering >  809: unexpected token at '' (JSON parser error ruby3.0.4 mac os catalina
809: unexpected token at '' (JSON parser error ruby3.0.4 mac os catalina

Time:06-08

I have just started learning ruby and trying to learn extracting web data. I am using samplewebapp code given in a sites API documentation

On executing the test.rb file as given below it generates a token.

The token.json file contains the following

{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzY2U1NjFhMC01ZmE5LTQ5NjUtYTQ2Mi01NmI2MzEzNjRlZGMiLCJqdGkiOiJmMjc0ZTgwM2FmZjVlMTFiMTAzNzIwMzAwNzRlNDRhZDE3ODg3ZjAzOGQ2ODk0OWIwNzVkMmQ5N2E2MjAwYzc5ZWRhNzU4MmQ3MTg1MTc1YiIsImlhdCI6MTY1NDU2OTc0MS41MjgxNTUsIm5iZiI6MTY1NDU2OTc0MS41MjgxNTcsImV4cCI6MTY1NDU3MzM0MS41MjgwMzksInN1YiI6IjE5NGFlNTU5LTU5OWMtNDQ2ZC1hOTRhLWM2MTIyYjZkMTA2ZiIsInNjb3BlcyI6W10sImNyZWRpdHNfcmVtYWluaW5nIjo0NzAwLCJyYXRlX2xpbWl0cyI6W3sicmF0ZSI6NSwiaW50ZXJ2YWwiOjYwfV19.XoN5A-H8Z7d8p_0e2rCcyV4yWO9MAF3TZlHk5VP5NjUEqtTXTVYKfKuzidYDs7K8ZzAtWzyt3aR5VSUG0_nw-uPd7Z3_Y75alQMqa2b5rHGn5JFWH7nuAriskr26WSCqAdj4cNjccPORryRr5sYKwpE4Y4kTG0IX_8frvwYxwp-8wFpLLj98K3axwN7CCpWdnPDSzuMqmH6tSpF0XhdYxB5LTVH0AyH7lN0S0_Lftq0b3sOLIvEaTfNkuRGNqwLkBYFkHFuPqwrKd8RJhC2W1QZhrmUw3eYnh-0iQABGk2V0skIqDlb6BbQ5GFX6MXgiXAc-h5Ndda7pZ5N5UCQU3g","expires_at":1654573341}

However it also generates a JSON parser error as under

/Users/mm/.rbenv/versions/3.0.4/lib/ruby/3.0.0/json/common.rb:216:in `parse': 809: unexpected token at '' (JSON::ParserError)
    from /Users/mm/.rbenv/versions/3.0.4/lib/ruby/3.0.0/json/common.rb:216:in `parse'
    from /Users/mm/Desktop/prokerala/client.rb:21:in `parseResponse'
    from /Users/mm/Desktop/prokerala/client.rb:99:in `get'

I googled around for a while and some of the responses talk about the issues between double and single quotes.. I tried changing those also but it doesn't work.

I have also tried running it with system ruby - which gives a different error

Would appreciate very much if someone could explain what the error is / logic behind this.. Also I am not clear about the error message itself. The message talks about parse error 809:"unexpected token" on column no 809 of the token there is nothing.. Am i reading it wrong?

code used in test.rb file


client = ApiClient.new('YOUR CLIENT_ID', 'YOUR CLIENT_SECRET');

result = client.get('v2/astrology/thirumana-porutham/advanced', {
    :girl_nakshatra => 4,
    :girl_nakshatra_pada => 2,
    :boy_nakshatra => 26,
    :boy_nakshatra_pada => 3
})
puts JSON.pretty_generate(result)

code used in client.rb file

require 'net/http'
require 'json'

class ApiError < StandardError
end

class ApiClient
    BASE_URL = "https://api.prokerala.com/"
    # Make sure that the following file path is set to a location that is not publicly accessible
    TOKEN_FILE = "./token.json"

    def initialize(clientId, clientSecret)
        # Instance variables
        @clientId = clientId
        @clientSecret = clientSecret
    end

    def parseResponse(response)
        content = response.body
        res = JSON.parse(content)

        if res.key?('access_token')
            return res
        end

        if res['status'] == "error"
            raise ApiError, res['errors'].map {|e| e['detail']}.join("\n")
        end

        if res['status'] != "ok"
            raise "HTTP request failed"
        end

        return res
    end

    def saveToken(token)
        # Cache the token until it expires.
        File.open(ApiClient::TOKEN_FILE,"w") do |f|
            token = {
                :access_token => token['access_token'],
                :expires_at => Time.now.to_i   token['expires_in']
            }
            f.write(token.to_json)
        end
    end

    def getTokenFromCache
        if not File.file?(ApiClient::TOKEN_FILE)
            return nil
        end

        begin
            # Fetch the cached token, and return if not expired
            text = File.read(ApiClient::TOKEN_FILE)
            token = JSON.parse(text)

            if token['expires_at'] < Time.now.to_i
                return nil
            end

            return token['access_token']
        rescue JSON::ParserError
            return nil
        end
    end

    def fetchNewToken
        params = {
            :grant_type => 'client_credentials',
            :client_id => @clientId,
            :client_secret => @clientSecret
        }

        res = Net::HTTP.post_form(URI(ApiClient::BASE_URL   'token'), params)
        token = parseResponse(res)

        saveToken(token)

        return token['access_token']
    end

    def get(endpoint, params)
        # Try to fetch the access token from cache
        token = getTokenFromCache
        # If failed, request new token
        token ||= fetchNewToken

        uri = URI(ApiClient::BASE_URL   endpoint)
        uri.query = URI.encode_www_form(params)

        req = Net::HTTP::Get.new(uri.to_s, {'Authorization' => 'Bearer '   token})

        res = Net::HTTP.start(uri.hostname) do |http|
            http.request(req)
        end

        return parseResponse(res)
    end
end

running the test file using ruby 3.0.4 gives the a JSON parse error. Full error reproduced as below

/Users/mm/.rbenv/versions/3.0.4/lib/ruby/3.0.0/json/common.rb:216:in `parse': 809: unexpected token at '' (JSON::ParserError)
    from /Users/mm/.rbenv/versions/3.0.4/lib/ruby/3.0.0/json/common.rb:216:in `parse'
    from /Users/mm/Desktop/prokerala/client.rb:21:in `parseResponse'
    from /Users/mm/Desktop/prokerala/client.rb:99:in `get'
    from test.rb:11:in `<main>'

CodePudding user response:

I executed the above code and from this, we are getting #<Net::HTTPMovedPermanently 301 Moved Permanently readbody=true> as response and response body as empty string '', which results in error in parsing the body.

Since, API endpoint is secure with https, we need set use_ssl: true before starting the session. Try below code and it will fix the issue.

      res = Net::HTTP.start(uri.hostname, use_ssl: true) do |http|
        http.request(req)
      end
  • Related