Groovy HTTPBuilder producing error when parsing valid json - json

I'm a Groovy novice and trying to connect to the GitHub API from a groovy script however I am getting a strange error when HTTPBuilder tries to parse the JSON response.
My simple script is as follows
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.2' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def apiToken = '[api_token]'
def http = new HTTPBuilder( 'https://api.github.com/' )
// perform a GET request, expecting JSON response data
http.request( GET, JSON ) {
uri.path = '/orgs/octokit/repos'
headers.'Accept' = 'application/json'
headers.'Authorization' = 'Basic ' + (apiToken + ':').bytes.encodeBase64().toString()
headers.'User-Agent' = '[username]'
// response handler for a success response code:
response.success = { resp, json ->
println resp.statusLine
}
// handler for any failure status code:
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
}
}
But when the JSON is parsed I get the following Error
Sep 06, 2014 10:21:54 PM groovyx.net.http.HTTPBuilder$1 handleResponse
WARNING: Error parsing 'application/json; charset=utf-8' response
groovy.json.JsonException: expecting '}' or ',' but got current char '"' with an int value of 34
The current character read is '"' with an int value of 34
expecting '}' or ',' but got current char '"' with an int value of 34
line number 1
index number 256
[{"id":417862,"name":"octokit.rb","full_name":"octokit/octokit.rb","owner":{"login":"octokit","id":3430433,"avatar_url":"https://avatars.githubusercontent.com/u/3430433?v=2","gravatar_id":"43f38795089d56a2a7092b7d0c71fa76","url":"h
................................................................................................................................................................................................................................................................^
at groovy.json.internal.JsonParserCharArray.complain(JsonParserCharArray.java:162)
at groovy.json.internal.JsonParserCharArray.decodeJsonObject(JsonParserCharArray.java:152)
at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:196)
at groovy.json.internal.JsonParserCharArray.decodeJsonObject(JsonParserCharArray.java:140)
at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:196)
at groovy.json.internal.JsonParserCharArray.decodeJsonArray(JsonParserCharArray.java:346)
at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:192)
at groovy.json.internal.JsonParserCharArray.decodeValue(JsonParserCharArray.java:166)
at groovy.json.internal.JsonParserCharArray.decodeFromChars(JsonParserCharArray.java:45)
at groovy.json.internal.JsonParserCharArray.parse(JsonParserCharArray.java:409)
at groovy.json.internal.BaseJsonParser.parse(BaseJsonParser.java:121)
at groovy.json.JsonSlurper.parse(JsonSlurper.java:224)
at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:280)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1207)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1074)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:439)
at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:560)
at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:489)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:515)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:434)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:383)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
at sprint-snapshot.run(sprint-snapshot.groovy:11)
at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:258)
at groovy.lang.GroovyShell.run(GroovyShell.java:502)
at groovy.lang.GroovyShell.run(GroovyShell.java:491)
at groovy.ui.GroovyMain.processOnce(GroovyMain.java:650)
at groovy.ui.GroovyMain.run(GroovyMain.java:381)
at groovy.ui.GroovyMain.process(GroovyMain.java:367)
at groovy.ui.GroovyMain.processArgs(GroovyMain.java:126)
at groovy.ui.GroovyMain.main(GroovyMain.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:106)
at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128)
Caught: groovyx.net.http.ResponseParseException: OK
groovyx.net.http.ResponseParseException: OK
at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:495)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:515)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:434)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:383)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at sprint-snapshot.run(sprint-snapshot.groovy:11)
Caused by: groovy.json.JsonException: expecting '}' or ',' but got current char '"' with an int value of 34
The current character read is '"' with an int value of 34
expecting '}' or ',' but got current char '"' with an int value of 34
line number 1
index number 256
[{"id":417862,"name":"octokit.rb","full_name":"octokit/octokit.rb","owner":{"login":"octokit","id":3430433,"avatar_url":"https://avatars.githubusercontent.com/u/3430433?v=2","gravatar_id":"43f38795089d56a2a7092b7d0c71fa76","url":"h
................................................................................................................................................................................................................................................................^
at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:280)
at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:560)
at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:489)
... 7 more
The error seems to suggest invalid JSON however I have confirmed the response is indeed valid, as you would expect from the Github API.
What is even stranger, is if I remove the 'Authorization' header completely and send the request unauthenticated, it works fine :S

It's an issue with the latest release of Groovy. I had the same issue. Your code should work with version of Groovy before 2.3.0. Optionally you can try a different default JSONParserType for HTTPBuilder.
See
http://beta.groovy-lang.org/docs/groovy-2.3.0/html/gapi/groovy/json/JsonSlurper.html
http://alfonsorv.com/instruct-groovy-httpbuilder-to-handle-a-json-response-with-wrong-content-type/

Here is my code work-around
/*
* Normally we would use the method "request(GET, JSON)" to return a json result, but with the release
* of groovy 2.3.0, which included extensive changes to JSON parsing, the result returned from the
* Artifactory REST API call 'File List' could not be parsed by HTTPBuilder's default JSON parser.
*
* Specifying the content type as TEXT removes the parsing from the call. Code was added to parse the returned
* text into JSON using the more lenient 'LAX' parser.
*/
http.request( GET, TEXT ) {
//Since content type is text, we need to specify that a json response is acceptable.
headers.Accept = 'application/json'
headers.'User-Agent' = USER_AGENT
response.success = { respnse, reader ->
def jsonText = reader.text
def parser = new JsonSlurper().setType(JsonParserType.LAX)
def jsonResp = parser.parseText(jsonText)
//Add up the size of all the files in this directory
//
jsonResp.files.each {
directorySize = directorySize + Integer.parseInt("${it.size}".toString())
}
}
}

def bufferedText = response.entity.content.getText( ParserRegistry.getCharset( response ) ).trim()
def result = new JsonSlurper().parseText( bufferedText )

def 'test hello resource'(){
when:
def info =""
// http.auth.basic('sysadmin', 'yax64smi')
// http.ignoreSSLIssues()//add for this issue Groovy:SSLPeerUnverifiedException: peer not authenticated new version (0.7.1) of HttpBuilder introduces method:ignoreSSLIssues()
http.request( GET,JSON ) {
uri.path = '/hello/'
//headers.'Authorization' = 'Basic c3lzYWRtaW46eWF4NjRzbWk='
//headers.'Authorization' = "Basic ${"username:password".bytes.encodeBase64().toString()}"
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
headers.'Content-Type' = 'application/json'
headers.Accept = 'application/json'
response.success = { resp ->
def parser = new JsonSlurper().setType(JsonParserType.LAX)
def jsonResptext = parser.parseText( resp.entity.content.getText())
println "PUT response status: ${resp.statusLine}"
assert resp.statusLine.statusCode == 200 ||resp.statusLine.statusCode ==201 ||resp.statusLine.statusCode ==202
info = resp.statusLine.statusCode
// def bufferedText = resp.entity.content.getText( ParserRegistry.getCharset( resp ) ).trim()
println 'Headers: -----------Response data: -----'
println "Content-Type: ${resp.headers.'Content-Type'}"
println jsonResptext
}
response.failure = { resp -> println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}" }
}
println "Result:\n"+info
then:
assert info ==200 || info ==201 || info ==202
}

Related

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

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>'
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

Groovy - Parse XML Response, Select Fields, Create New File

I think I've read every Groovy parsing question on here but I can't seem to find my exact scenario so I'm reaching out for help - please be kind, I'm new to Groovy and I've really bitten off more than I can chew in this latest endeavor.
So I have this XML Response:
<?xml version="1.0" encoding="UTF-8"?>
<worklogs date_from="2020-04-19 00:00:00" date_to="2020-04-25 23:59:59" number_of_worklogs="60" format="xml" diffOnly="false" errorsOnly="false" validOnly="false" addDeletedWorklogs="true" addBillingInfo="false" addIssueSummary="true" addIssueDescription="false" duration_ms="145" headerOnly="false" userName="smm288" addIssueDetails="false" addParentIssue="false" addUserDetails="true" addWorklogDetails="false" billingKey="" issueKey="" projectKey="" addApprovalStatus="true" >
<worklog>
<worklog_id></worklog_id>
<jira_worklog_id></jira_worklog_id>
<issue_id></issue_id>
<issue_key></issue_key>
<hours></hours>
<work_date></work_date>
<username></username>
<staff_id />
<billing_key></billing_key>
<billing_attributes></billing_attributes>
<activity_id></activity_id>
<activity_name></activity_name>
<work_description></work_description>
<parent_key></parent_key>
<reporter></reporter>
<external_id />
<external_tstamp />
<external_hours></external_hours>
<external_result />
<customField_11218></customField_11218>
<customField_12703></customField_12703>
<customField_12707></customField_12707>
<hash_value></hash_value>
<issue_summary></issue_summary>
<user_details>
<full_name></full_name>
<email></email>
<user-prop key="auto_approve_timesheet"></user-prop>
<user-prop key="cris_id"></user-prop>
<user-prop key="iqn_gl_string"></user-prop>
<user-prop key="is_contractor"></user-prop>
<user-prop key="is_employee"></user-prop>
<user-prop key="it_leadership"></user-prop>
<user-prop key="primary_role"></user-prop>
<user-prop key="resource_manager"></user-prop>
<user-prop key="team"></user-prop>
</user_details>
<approval_status></approval_status>
<timesheet_approval>
<status></status>
<status_date></status_date>
<reviewer></reviewer>
<actor></actor>
<comment></comment>
</timesheet_approval>
</worklog>
....
....
</worklogs>
And I'm retrieving this XML Response from an API call so the response is held within an object. NOTE: The sample XML above is from Postman.
What I'm trying to do is the following:
1. Only retrieve certain values from this response from all the nodes.
2. Write the values collected to a .json file.
I've created a map but now I'm kind of stuck on how to parse through it and create a .json file out of the fields I want.
This is what I have thus far
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
#Grab('oauth.signpost:signpost-core:1.2.1.2')
#Grab('oauth.signpost:signpost-commonshttp4:1.2.1.2')
import groovyx.net.http.RESTClient
import groovyx.net.http.Method
import static groovyx.net.http.ContentType.*
import groovyx.net.http.HttpResponseException
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.json.*
// User Credentials
def jiraAuth = ""
// JIRA Endpoints
def jiraUrl = "" //Dev
def jiraUrl = "" //Production
// Tempo API Tokens
//def tempoApiToken = "" //Dev
//def tempoApiToken = "" //Production
// Define Weekly Date Range
def today = new Date()
def lastPeriodStart = today - 8
def lastPeriodEnd = today - 2
def dateFrom = lastPeriodStart.format("yyyy-MM-dd")
def dateTo = lastPeriodEnd.format("yyyy-MM-dd")
def jiraClient = new RESTClient(jiraUrl)
jiraClient.ignoreSSLIssues()
def headers = [
"Authorization" : "Basic " + jiraAuth,
"X-Atlassian-token": "no-check",
"Content-Type" : "application/json"
]
def response = jiraClient.get(
path: "",
query: [
tempoApiToken: "${tempoApiToken}",
format: "xml",
dateFrom: "${dateFrom}",
dateTo: "${dateTo}",
addUserDetails: "true",
addApprovalStatus: "true",
addIssueSummary: "true"
],
headers: headers
) { response, worklogs ->
println "Processing..."
// Start building the Output - Creates a Worklog Map
worklogs.worklog.each { worklognodes ->
def workLog = convertToMap(worklognodes)
// Print out the Map
println (workLog)
}
}
// Helper Method
def convertToMap(nodes) {
nodes.children().collectEntries {
if (it.name() == 'user-prop') {
[it['#key'], it.childNodes() ? convertToMap(it) : it.text()]
} else {
[it.name(), it.childNodes() ? convertToMap(it) : it.text()]
}
}
}
I'm only interested in parsing out the following fields from each node:
<worklogs>
<worklog>
<hours>
<work_date>
<billing_key>
<customField_11218>
<issue_summary>
<user_details>
<full_name>
<user-prop key="auto_approve_timesheet">
<user-prop key="it_leadership">
<user-prop key="resource_manager">
<user-prop key="team">
<user-prop key="cris_id">
<user-prop key="iqn_id">
<approval_status>
</worklog>
...
</worklogs>
I've tried the following:
1. Converting the workLog to a json string (JsonOutput.toJson) and then converting the json string to prettyPrint (JsonOutput.prettyPrint) - but this just returns a collection of .json responses which I can't do anything with (thought process was, this is as good as I can get and I'll just use a .json to .csv converter and get rid of what I don't want) - which is not the solution I ultimately want.
2. Printing the map workLog just returns little collections which I can't do anything with either
3. Create a new file using File and creating a .json file of workLog but again, it doesn't translate well.
The results of the println for workLog is here (just so everyone can see that the response is being held and the map matches the XML response).
[worklog_id: , jira_worklog_id: , issue_id: , issue_key: , hours: , work_date: , username: , staff_id: , billing_key: , billing_attributes: , activity_id: , activity_name: , work_description: , parent_key: , reporter: , external_id:, external_tstamp:, external_hours: , external_result:, customField_11218: , hash_value: , issue_summary: , user_details:[full_name: , email: , auto_approve_timesheet: , cris_id: , iqn_gl_approver: , iqn_gl_string: , iqn_id: , is_contractor: , is_employee: , it_leadership: , primary_role: , resource_manager: , team: ], approval_status: , timesheet_approval:[status: ]]
I would so appreciate it if anyone could offer some insights on how to move forward or even documentation that has good examples of what I'm trying to achieve (Apache's documentation is sorely lacking in examples, in my opinion).
It's not all of the way there. But, I was able to get a JSON file created with the XML and Map. From there I can just use the .json file to create a .csv and then get rid of the columns I don't want.
// Define Weekly Date Range
def today = new Date()
def lastPeriodStart = today - 8
def lastPeriodEnd = today - 2
def dateFrom = lastPeriodStart.format("yyyy-MM-dd")
def dateTo = lastPeriodEnd.format("yyyy-MM-dd")
def jiraClient = new RESTClient(jiraUrl)
jiraClient.ignoreSSLIssues()
// Creates and Begins the File
File file = new File("${dateFrom}_RPT05.json")
file.write("")
file.append("[\n")
// Defines the File
def arrplace = 0
def arrsize = 0
def headers = [
"Authorization" : "Basic " + jiraAuth,
"X-Atlassian-token": "no-check",
"Content-Type" : "application/json"
]
def response = jiraClient.get(
path: "/plugins/servlet/tempo-getWorklog/",
query: [
tempoApiToken: "${tempoApiToken}",
format: "xml",
dateFrom: "${dateFrom}",
dateTo: "${dateTo}",
addUserDetails: "true",
addApprovalStatus: "true",
addIssueSummary: "true"
],
headers: headers
) { response, worklogs ->
println "Processing..."
// Gets Size of Array
worklogs.worklog.each { worklognodes ->
arrsize = arrsize+1 }
// Start Building the Output - Creates a Worklog Map
worklogs.worklog.each { worklognodes ->
worklognodes = convertToMap(worklognodes)
// Convert Map to a JSON String
def json_str = JsonOutput.toJson(worklognodes)
// Adds Row to File
file.append(json_str)
arrplace = arrplace+1
if(arrplace<arrsize)
{file.append(",")}
file.append("\n")
print "."
}
}
file.append("]")
// Helper Method
def convertToMap(nodes) {
nodes.children().collectEntries {
if (it.name() == 'user-prop') {
[it['#key'], it.childNodes() ? convertToMap(it) : it.text()]
} else {
[it.name(), it.childNodes() ? convertToMap(it) : it.text()]
}
}
}
The output is a collection/array of worklogs.

Python 3 Gzip json for post on an API

Having a bit of trouble getting a gzipped JSON payload with python 3
def post_data ( data ) :
method_name = json.loads(data)['subject'][4][0][1]
instance = json.loads(data)['serialNumber']
timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
utc_now = datetime.datetime.utcnow().strftime("%m-%d-%Y %H:%M:%S")
not_after = datetime.datetime.strptime(json.loads(data)['notAfter'], "%b %d %H:%M:%S %Y GMT" ).strftime("%m-%d-%Y %H:%M:%S")
days = datetime.datetime.strptime(not_after, "%m-%d-%Y %H:%M:%S")-\
datetime.datetime.strptime(utc_now, "%m-%d-%Y %H:%M:%S")
values = days.days
raw_json = '''{"MetricReports":[{
"Metadata":{
"MinPeriod":"FiveMinute",
"MaxPeriod":"FiveMinute"
},
"Namespace":"Schema/Service",
"Metrics":[{
"Dimensions":{
"DataSet":"NONE",
"Marketplace":"PDX",
"HostGroup":"ALL",
"Host":"host.com",
"ServiceName":"Server",
"MethodName":"%s",
"Client":"ALL",
"MetricClass":"instance",
"Instance":"%s"
},
"MetricName":"daysToExpiry",
"Timestamp":"%s",
"Type":"MetricsLine",
"Unit":"None",
"Values":%s
}
]}
]}''' %(method_name, instance, timestamp, values)
headers = {'content-type' : 'application/x-gzip'}
putUrl = 'http://api-pdx.com/'
session = boto3.Session()
credentials = session.get_credentials()
region = 'us-west-2'
service = 'monitor-api'
auth = AWS4Auth(
credentials.access_key,
credentials.secret_key,
region,
service,
session_token = credentials.token)
r = requests.post(url = putUrl, json = gzip.compress(raw_json) , auth = auth, headers = headers, verify=False)
print(r.content)
get_data()
post_data(data)
I need to compress the raw_json because the API is expecting a gzipped attachment. The API is spitting back "The HTTP request is invalid. Reason: Invalid JSON attachment:Not in GZIP format" if I attempt to send the JSON as is.
I tried the gzip.compress, but it says : memoryview: a bytes-like object is required, not 'str'
so I tried gzip.compress(json.dumps(raw_json).encode('utf-8')) and that says Object of type bytes is not JSON serializable
To send a binary data with requests.post method they should be passed as data argument, not as json:
requests.post(url = putUrl,
data = gzip.compress(json.dumps(raw_json).encode('utf-8')),
auth = auth,
headers = headers,
verify=False)

Passing arguments as json object

I am trying to link my django web app to Azure ML API. I do have Django form with all the required inputs for my Azure API.
def post(self,request):
form = CommentForm(request.POST)
url = 'https://ussouthcentral.services.azureml.net/workspaces/7061a4b24ea64942a19f74ed36e4b438/services/ae2c257d6e164dca8d433ad1a1f9feb4/execute?api-version=2.0&format=swagger'
api_key = # Replace this with the API key for the web service
headers = {'Content-Type':'application/json', 'Authorization':('Bearer '+ api_key)}
if form.is_valid():
age = form.cleaned_data['age']
bmi = form.cleaned_data['bmi']
args = {"age":age,"bmi":bmi}
json_data = str.encode(json.dumps(args))
print(type(json_data))
r= urllib.request.Request(url,json_data,headers)
try:
response = urllib.request.urlopen(r)
result = response.read()
print(result)
except urllib.request.HTTPError as error:
print("The request failed with status code: " + str(error.code))
print(json_data)
# Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
print(error.info())
print(json.loads(error.read()))
return render(request,self.template_name)
When i try to submit the form i am getting type error -
TypeError('POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.',)
Getting status code - 400 and below error
{'error': {'code': 'BadArgument', 'message': 'Invalid argument provided.', 'details': [{'code': 'RequestBodyInvalid', 'message': 'No request body provided or error in deserializing the request body.'}]}}
Arguments are using print(json_data) -
b'{"age": 0, "bmi": 22.0}'
Can someone help me on this?
Try to use JsonResponse:
https://docs.djangoproject.com/en/2.1/ref/request-response/#jsonresponse-objects
Also, I don't think you need a template for API response.
return JsonResponse({'foo': 'bar'})
Thanks all. I found the error it was the data which was not in proper order.

error in json in corona lua

hi i have found a tutorial on how to use post json in lua.
here is the code :
http = require("socket.http")
crypto = require("crypto")
ltn12 = require("ltn12")
url = require("socket.url")
local json = require("json")
local commands_json =
{
["message"] = "Hello",
}
print (commands_json)
local json = {}
json.api_key = "6_192116334"
json.ver = 1
json.commands_json = json.encode(commands_json)
json.commands_hash = crypto.digest(crypto.md5, json.commands_json .. 'hkjhkjhkjh')
local post = "api=" .. url.escape(Json.Encode(json))
local response = {}
local r, c, h = http.request {
url = "http://127.0.0.1/?page=api",
method = "POST",
headers = {
["content-length"] = #post,
["Content-Type"] = "application/x-www-form-urlencoded"
},
source = ltn12.source.string(post),
sink = ltn12.sink.table(response)
}
local path = system.pathForFile("r.txt", system.DocumentsDirectory)
local file = io.open (path, "w")
file:write (Json.Encode(json) .. "\n")
file:write (post .. "\n")
file:write (response[1] .. "\n")
io.close (file)
json = Json.Decode(table.concat(response,''))
native.showAlert("hey", json.commands[1].tot_nbr_rows)
now i got these error:
Windows simulator build date: Dec 9 2011 # 14:01:29
Copyright (C) 2009-2011 A n s c a , I n c .
Version: 2.0.0
Build: 2011.704
table: 0346D6D0
Runtime error
...nistrator\my documents\corona projects\json\main.lua:17: attempt to c
all field 'encode' (a nil value)
stack traceback:
[C]: in function 'encode'
...nistrator\my documents\corona projects\json\main.lua:17: in main chun
k
Runtime error: ...nistrator\my documents\corona projects\json\main.lua:17: attem
pt to call field 'encode' (a nil value)
stack traceback:
[C]: in function 'encode'
...nistrator\my documents\corona projects\json\main.lua:17: in main chun
k
i don't know why i got the error from encode.
can anyone can help me about my case?
thanks in advance ...
This includes the Json code provided externally, likely with an encode function:
local json = require("json")
This throws away your old json variable and replaces it with an empty table:
local json = {}
And this tries to call json.encode which is now undefined since you redefined json as an empty table above:
json.commands_json = json.encode(commands_json)
The solution is to pick a different variable name.