I'm building a node wrapper for an external API and am having issues parsing the JSON response. The following code makes the request:
我正在为外部API构建节点包装器,并且在解析JSON响应时遇到问题。以下代码发出请求:
https = require "https"
querystring = require "querystring"
API_HOST = "api.lob.com"
API_PATH = "/v1"
startResponseHandler = (req, cb) ->
if typeof cb isnt "function" then console.log "Error: callback needs to be a function!"
req.on 'response', (res) ->
response = ''
res.setEncoding 'utf8'
res.on 'data', (stream) ->
response += stream
res.on 'end', () ->
error = null
try
response = JSON.parse response
if res.statusCode != 200 or 201
response = null
error = new Error response.error.message
error.name = response.error.type
error.code = response.error.code
error.param = response.error.param
catch e
error = new Error "Invalid JSON"
response = null
cb error, response
req.on 'error', (error) ->
cb error
module.exports = lob = (api_key) ->
# This function makes the request
makeRequest = (method, path, data, cb) ->
data = querystring.stringify data
options =
hostname: API_HOST
path: "#{API_PATH}/#{path}"
method: method
auth: "#{api_key}:"
headers:
'Content-Type' : 'application/x-www-form-urlencoded'
'Content-Length' : data.length
req = https.request options
startResponseHandler req, cb
req.write data if method is "POST" or "PUT"
req.end()
# GET, POST, DELETE, PUT functions
_get = (path, cb) ->
makeRequest "GET", path, {}, cb
_post = (path, data, cb) ->
makeRequest "POST", path, data, cb
_del = (path, cb) ->
makeRequest "DELETE", path, {}, cb
_put = (path, data, cb) ->
makeRequest "PUT", path, data, cb
# Jobs
jobs:
createJob: (data, cb) ->
_post "/jobs/", data, cb
And the below code was written to test the wrapper:
编写下面的代码来测试包装器:
api_key = "test_0dc8d51e0acffcb1880e0f19c79b2f5b0cc"
lob = require('../src/lob')(api_key)
should = require("should")
chai = require("chai")
data =
name: "Michigan fan letter"
to: "adr_43769b47aed248c2"
from: "adr_7f9ece71fbca3796"
object1: "obj_7ca5f80b42b6dfca"
object2: "obj_12128d3aad2aa98f"
describe "Job", ->
@timeout(10000)
describe "create", ->
it "should create a job with address_id", (done) ->
lob.jobs.createJob data , (new_job) ->
new_job['name'].should.equal(data['name'])
done()
However, when I run the mocha test ($ mocha --compilers coffee:coffee-script
) I receive the following error:
但是,当我运行mocha测试($ mocha --compilers coffee:coffee-script)时,我收到以下错误:
1) Job create should create a job with address_id:
+ expected - actual
+"Michigan fan letter"
-"Error"
EDIT
Below is the response from stream
inside res.on 'data'
:
以下是来自res.on'data'内的流的响应:
{
"id": "job_7ecc50bea15178b8e07a",
"name": "Michigan fan letter",
"price": "1.26",
"to": {
"id": "adr_43769b47aed248c2",
"name": "Harry Zhang",
"email": "harry@lob.com",
"phone": "5555555555",
"address_line1": "123 Test Street",
"address_line2": "Unit 199",
"address_city": "Mountain View",
"address_state": "CA",
"address_zip": "94085",
"address_country": "UNITED STATES",
"date_created": "2013-07-20T05:53:25+00:00",
"date_modified": "2013-07-20T05:53:25+00:00",
"object": "address"
},
"from": {
"id": "adr_7f9ece71fbca3796",
"name": "Harry Zhang",
"email": "harry@lob.com",
"phone": "5555555555",
"address_line1": "123 Test Avenue",
"address_line2": "Unit 401",
"address_city": "Seattle",
"address_state": "WA",
"address_zip": "98122",
"address_country": "UNITED STATES",
"date_created": "2013-07-20T05:55:19+00:00",
"date_modified": "2013-07-20T05:55:19+00:00",
"object": "address"
},
"status": "processed",
"tracking": null,
"packaging": {
"id": "1",
"name": "Smart Packaging",
"description": "Automatically determined optimal packaging for safe and secure delivery",
"object": "packaging"
},
"service": null,
"objects": [
{
"id": "obj_7ca5f80b42b6dfca",
"name": "Michigan is great",
"quantity": "1",
"full_bleed": "0",
"double_sided": "0",
"date_created": "2013-07-20T05:57:32+00:00",
"date_modified": "2013-07-20T05:57:32+00:00",
"setting": {
"id": "101",
"type": "Documents",
"description": "Color Document",
"paper": "20lb Paper Standard",
"width": "8.500",
"length": "11.000",
"color": "Color",
"notes": "50 cents per extra page",
"object": "setting"
},
"url": "http://assets.lob.com/obj_7ca5f80b42b6dfca",
"object": "object"
},
{
"id": "obj_12128d3aad2aa98f",
"name": "GO BLUE",
"quantity": "1",
"full_bleed": "0",
"double_sided": "0",
"date_created": "2013-07-31T00:58:35+00:00",
"date_modified": "2013-07-31T00:58:35+00:00",
"setting": {
"id": "100",
"type": "Documents",
"description": "Black and White Document",
"paper": "20lb Paper Standard",
"width": "8.500",
"length": "11.000",
"color": "Black and White",
"notes": "12 cents per extra page",
"object": "setting"
},
"url": "http://assets.lob.com/obj_12128d3aad2aa98f",
"object": "object"
}
],
"date_created": "2014-01-25T03:10:10+00:00",
"date_modified": "2014-01-25T03:10:10+00:00",
"object": "job"
}
Which exactly matches up to the example response in the documentation
这完全符合文档中的示例响应
{
"id": "job_754d8b14dd31587d6873",
"name": "Michigan fan letter",
"price": "0.96",
"to": {
"id": "adr_43769b47aed248c2",
"name": "Harry Zhang",
"email": "harry@lob.com",
"phone": "5555555555",
"address_line1": "123 Test Street",
"address_line2": "Unit 199",
"address_city": "Mountain View",
"address_state": "CA",
"address_zip": "94085",
"address_country": "UNITED STATES",
"date_created": "2013-07-20T05:53:25+00:00",
"date_modified": "2013-07-20T05:53:25+00:00",
"object": "address"
},
"from": {
"id": "adr_7f9ece71fbca3796",
"name": "Harry Zhang",
"email": "harry@lob.com",
"phone": "5555555555",
"address_line1": "123 Test Avenue",
"address_line2": "Unit 401",
"address_city": "Seattle",
"address_state": "WA",
"address_zip": "98122",
"address_country": "UNITED STATES",
"date_created": "2013-07-20T05:55:19+00:00",
"date_modified": "2013-07-20T05:55:19+00:00",
"object": "address"
},
"status": "processed",
"tracking": null,
"packaging": {
"id": "1",
"name": "Smart Packaging",
"description": "Automatically determined optimal packaging for safe and secure delivery",
"object": "packaging"
},
"service": null,
"objects": [
{
"id": "obj_7ca5f80b42b6dfca",
"name": "Michigan is great",
"quantity": "1",
"full_bleed": "0",
"double_sided": "0",
"date_created": "2013-07-20T05:57:32+00:00",
"date_modified": "2013-07-20T05:57:32+00:00",
"setting": {
"id": "101",
"type": "Documents",
"description": "Color Document",
"paper": "20lb Paper Standard",
"width": "8.500",
"length": "11.000",
"color": "Color",
"notes": "50 cents per extra page",
"object": "setting"
},
"object": "object"
}
],
"date_created": "2014-01-18T19:52:27+00:00",
"date_modified": "2014-01-18T19:52:27+00:00",
"object": "job"
}
Here is the data from JSON.parse response
这是来自JSON.parse响应的数据
{ id: 'job_9973e060bd8147f97f5f',
name: 'Michigan fan letter',
price: '1.26',
to:
{ id: 'adr_43769b47aed248c2',
name: 'Harry Zhang',
email: 'harry@lob.com',
phone: '5555555555',
address_line1: '123 Test Street',
address_line2: 'Unit 199',
address_city: 'Mountain View',
address_state: 'CA',
address_zip: '94085',
address_country: 'UNITED STATES',
date_created: '2013-07-20T05:53:25+00:00',
date_modified: '2013-07-20T05:53:25+00:00',
object: 'address' },
from:
{ id: 'adr_7f9ece71fbca3796',
name: 'Harry Zhang',
email: 'harry@lob.com',
phone: '5555555555',
address_line1: '123 Test Avenue',
address_line2: 'Unit 401',
address_city: 'Seattle',
address_state: 'WA',
address_zip: '98122',
address_country: 'UNITED STATES',
date_created: '2013-07-20T05:55:19+00:00',
date_modified: '2013-07-20T05:55:19+00:00',
object: 'address' },
status: 'processed',
tracking: null,
packaging:
{ id: '1',
name: 'Smart Packaging',
description: 'Automatically determined optimal packaging for safe and secure delivery',
object: 'packaging' },
service: null,
objects:
[ { id: 'obj_7ca5f80b42b6dfca',
name: 'Michigan is great',
quantity: '1',
full_bleed: '0',
double_sided: '0',
date_created: '2013-07-20T05:57:32+00:00',
date_modified: '2013-07-20T05:57:32+00:00',
setting: [Object],
url: 'http://assets.lob.com/obj_7ca5f80b42b6dfca',
object: 'object' },
{ id: 'obj_12128d3aad2aa98f',
name: 'GO BLUE',
quantity: '1',
full_bleed: '0',
double_sided: '0',
date_created: '2013-07-31T00:58:35+00:00',
date_modified: '2013-07-31T00:58:35+00:00',
setting: [Object],
url: 'http://assets.lob.com/obj_12128d3aad2aa98f',
object: 'object' } ],
date_created: '2014-01-25T23:12:37+00:00',
date_modified: '2014-01-25T23:12:37+00:00',
object: 'job' }
1 个解决方案
#1
2
I see three problems in that code. I don't usually use CoffeeScript. So if I'm misreading please correct me:
我在该代码中看到了三个问题。我通常不使用CoffeeScript。所以,如果我误读,请纠正我:
-
The callback is called like this:
回调被调用如下:
cb error, response
First argument is an error object and the second argument is the response, however in the test the callback is like this:
第一个参数是一个错误对象,第二个参数是响应,但是在测试中回调是这样的:
lob.jobs.createJob data , (new_job) -> new_job['name'].should.equal(data['name'])
So
new_job
is the error object. This does not explain everything, however, because you are getting an error. But even if there were no error, the value ofnew_job
would not be the response.所以new_job是错误对象。但是,这并不能解释所有内容,因为您收到了错误。但即使没有错误,new_job的值也不会是响应。
The reason the test shows that the string
Error
is the actual value is thatError
objects have aname
field which is set to the name of the class of the exception. (Sonew Error().name
evaluates to"Error"
.)测试显示字符串Error是实际值的原因是Error对象具有名称字段,该字段设置为异常类的名称。 (所以新的Error()。name评估为“Error”。)
-
This section of code also looks incorrect:
这部分代码看起来也不正确:
try response = JSON.parse response if res.statusCode != 200 or 201 response = null error = new Error response.error.message error.name = response.error.type error.code = response.error.code error.param = response.error.param catch e error = new Error "Invalid JSON" response = null cb error, response
In the
if
branch theresponse
is set tonull
and then some fields ofresponse
are accessed. This will cause an exception. And this exception will then be interpreted as bad JSON due to the way thetry... catch
clause is set. Thetry... catch
clause should be narrowed to cover only theJSON.parse
call:在if分支中,响应设置为null,然后访问某些响应字段。这将导致异常。然后,由于try ... catch子句的设置方式,此异常将被解释为错误的JSON。应该缩小try ... catch子句以仅覆盖JSON.parse调用:
try response = JSON.parse response catch e error = new Error "Invalid JSON" response = null
-
This test is incorrect:
此测试不正确:
if res.statusCode != 200 or 201
It becomes JavaScript:
它变成了JavaScript:
if (res.statusCode !== 200 || 201)
The part after the
||
makes it always true. Something like the following CoffeeScript code seems to be what is intended:||之后的部分使它永远是真的。像下面的CoffeeScript代码似乎是预期的:
if res.statusCode not in [200, 201]
So it does not matter if the request is successful or not. Because of the third problem, theif
test will always be true, the branch always will be taken and the second problem will always occur. So the Mocha test will always fail.
因此,请求是否成功无关紧要。由于第三个问题,theif测试将始终为真,分支始终将被采用,并且第二个问题将始终发生。所以摩卡测试总会失败。
#1
2
I see three problems in that code. I don't usually use CoffeeScript. So if I'm misreading please correct me:
我在该代码中看到了三个问题。我通常不使用CoffeeScript。所以,如果我误读,请纠正我:
-
The callback is called like this:
回调被调用如下:
cb error, response
First argument is an error object and the second argument is the response, however in the test the callback is like this:
第一个参数是一个错误对象,第二个参数是响应,但是在测试中回调是这样的:
lob.jobs.createJob data , (new_job) -> new_job['name'].should.equal(data['name'])
So
new_job
is the error object. This does not explain everything, however, because you are getting an error. But even if there were no error, the value ofnew_job
would not be the response.所以new_job是错误对象。但是,这并不能解释所有内容,因为您收到了错误。但即使没有错误,new_job的值也不会是响应。
The reason the test shows that the string
Error
is the actual value is thatError
objects have aname
field which is set to the name of the class of the exception. (Sonew Error().name
evaluates to"Error"
.)测试显示字符串Error是实际值的原因是Error对象具有名称字段,该字段设置为异常类的名称。 (所以新的Error()。name评估为“Error”。)
-
This section of code also looks incorrect:
这部分代码看起来也不正确:
try response = JSON.parse response if res.statusCode != 200 or 201 response = null error = new Error response.error.message error.name = response.error.type error.code = response.error.code error.param = response.error.param catch e error = new Error "Invalid JSON" response = null cb error, response
In the
if
branch theresponse
is set tonull
and then some fields ofresponse
are accessed. This will cause an exception. And this exception will then be interpreted as bad JSON due to the way thetry... catch
clause is set. Thetry... catch
clause should be narrowed to cover only theJSON.parse
call:在if分支中,响应设置为null,然后访问某些响应字段。这将导致异常。然后,由于try ... catch子句的设置方式,此异常将被解释为错误的JSON。应该缩小try ... catch子句以仅覆盖JSON.parse调用:
try response = JSON.parse response catch e error = new Error "Invalid JSON" response = null
-
This test is incorrect:
此测试不正确:
if res.statusCode != 200 or 201
It becomes JavaScript:
它变成了JavaScript:
if (res.statusCode !== 200 || 201)
The part after the
||
makes it always true. Something like the following CoffeeScript code seems to be what is intended:||之后的部分使它永远是真的。像下面的CoffeeScript代码似乎是预期的:
if res.statusCode not in [200, 201]
So it does not matter if the request is successful or not. Because of the third problem, theif
test will always be true, the branch always will be taken and the second problem will always occur. So the Mocha test will always fail.
因此,请求是否成功无关紧要。由于第三个问题,theif测试将始终为真,分支始终将被采用,并且第二个问题将始终发生。所以摩卡测试总会失败。