Javascript 解析节点中的JSON API

Javascript 解析节点中的JSON API,javascript,json,node.js,coffeescript,mocha.js,Javascript,Json,Node.js,Coffeescript,Mocha.js,我正在为外部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

我正在为外部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
下面的代码是用来测试包装器的:

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()
但是,当我运行mocha测试(
$mocha--compilers coffee:coffee script
)时,我收到以下错误:

1) Job create should create a job with address_id:

      + expected - actual

      +"Michigan fan letter"
      -"Error"
编辑

下面是来自
内部
res.对“数据”
的响应:

{
    "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"
}
与中的示例响应完全匹配

以下是来自
JSON.parse response

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

我在代码中看到三个问题。我通常不使用咖啡脚本。因此,如果我误读了,请纠正我:

  • 回调的调用方式如下:

    cb error, response
    
    第一个参数是错误对象,第二个参数是响应,但是在测试中回调如下:

    lob.jobs.createJob data , (new_job) ->
             new_job['name'].should.equal(data['name'])
    
    因此,
    new\u job
    是错误对象。然而,这并不能解释一切,因为您得到了一个错误。但是,即使没有错误,
    new\u job
    的值也不会是响应

    测试显示字符串
    Error
    是实际值的原因是
    Error
    对象有一个
    name
    字段,该字段设置为异常类的名称。(因此
    newerror().name
    的计算结果为
    “Error”

  • 这段代码看起来也不正确:

    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
    
      if res.statusCode != 200 or 201
    
    if
    分支中,将
    响应设置为
    null
    ,然后访问
    response
    的一些字段。这将导致异常。由于
    try。。。设置catch
    子句。
    试试看。。。catch
    子句应缩小范围,仅涵盖
    JSON.parse
    调用:

    try
      response = JSON.parse response
    catch e
      error = new Error "Invalid JSON"
      response = 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
    
      if res.statusCode != 200 or 201
    
    它变成了JavaScript:

      if (res.statusCode !== 200 || 201)
    
    |
    后面的部分使其始终为真。下面的CoffeeScript代码似乎就是我们想要的:

      if res.statusCode not in [200, 201]
    

  • 因此,请求是否成功并不重要。由于第三个问题,
    if
    测试将始终为真,分支将始终被执行,第二个问题将始终出现。所以摩卡咖啡测试总是会失败。

    你看过《数据》中的
    stream
    吗?对于
    response
    inside
    res.on'end'
    。我没有记录内容,但是返回了一个201头,表明POST请求已成功完成。如果
    JSON.parse
    正在抱怨,那么可能您没有获得您认为正在获得的数据。好建议!我已经更新了这个问题,回答来自
    JSON.parse
    ,那么这是一个JSON字符串还是一个JavaScript对象
    JSON.parse
    需要一个string.quick note-在这个设置中,如果我进入
    console.log res.statusCode
    它将返回
    200
    ,因此它不会解决您当前的问题。很公平,但它仍然是糟糕的代码。有了我添加的第三点,我可能已经涵盖了所有内容。