如何为包含JSON数组的API端点创建Siesta转换器?

时间:2016-08-02 00:40:13

标签: ios json swift siesta-swift

我正在构建一个需要使用https://thecountedapi.com/api/counted框架向API端点Siesta发出GET请求的应用。端点返回一个JSON数组,就像https://api.github.com/users/ebelinski/repos之类的端点一样,它在Siesta示例Github Browser中使用。因此,我正试图让我的应用程序以一种方式使用Siesta。我创建了一项服务:

let API = Service(baseURL: "https://thecountedapi.com/api")

然后在application:didFinishLaunchingWithOptions中为我的端点创建变换器:

API.configureTransformer("/counted") {
  ($0.content as JSON).arrayValue.map(Incident.init)
}

其中,Incident是一个带有初始化器的结构,它接收一个JSON对象。

然后在我的视图控制器中,我创建了一个资源:

let resource = API.resource("/counted")

viewDidLoad

resource.addObserver(self)

viewWillAppear

resource.loadIfNeeded()

然后我在VC中有以下功能来收听更改:

func resourceChanged(resource: Resource, event: ResourceEvent) {
  print(resource.jsonArray)

  if let error = resource.latestError {
    print(error.userMessage)
    return
  }

  if let content: [Incident] = resource.typedContent() {
    print("content exists")
    incidents = content
  }

  print(incidents.count)
}

但是当我运行我的应用程序时,我得到了混合的结果。 print(resource.jsonArray)只打印[],我收到错误消息Cannot parse server response,如果我设置了Siesta.enabledLogCategories = LogCategory.detailed,我就会看到错误消息[Siesta:StateChanges] Siesta.Resource(https://thecountedapi.com/api/counted)[] received error: Error(userMessage: "Cannot parse server response", httpStatusCode: nil, entity: nil, cause: Optional(Siesta.Error.Cause.WrongTypeInTranformerPipeline(expectedType: "JSON", actualType: "__NSCFArray", transformer: Siesta.ResponseContentTransformer<SwiftyJSON.JSON, Swift.Array<TheCountedViewer.Incident…

如果我注释掉整个变换器,我会取得一些成功,print(resource.jsonArray)从端点打印出正确的数组。所以我的变压器在某种程度上肯定是错误的,但我认为我使用的基本上与Github浏览器中的变换器相同:

service.configureTransformer("/users/*/repos") {
    ($0.content as JSON).arrayValue.map(Repository.init)
}

我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

您的问题的关键线索隐藏在那个(可能不是理想的helfpul)日志消息中:

Siesta.Error.Cause.WrongTypeInTranformerPipeline
  expectedType: "JSON"
  actualType: "__NSCFArray"

它说你的变压器期望输入类型JSON,这是有道理的 - 你对($0.content as JSON)说了很多。但是,它得到类型__NSCFArray,这是NSArray的秘密内部支持类型。换句话说,它期望一个SwiftyJSON值,但它获得了NSJSONSerialization的原始输出。

为什么呢? GithubBrowser项目包含一个NSDict/NSArray → SwiftyJSON transformer configures in the parsing stage。该项目中的模型变换器都依赖于它。

要在项目中以相同的方式使用SwiftyJSON,您需要在您的示例项目中包含该变换器:

private let SwiftyJSONTransformer =
  ResponseContentTransformer
    { JSON($0.content as AnyObject) }

然后在设置服务时:

service.configure {
  $0.config.pipeline[.parsing].add(SwiftyJSONTransformer, contentTypes: ["*/json"])
}

(请注意,如果您对错误感兴趣,可能需要使用ResponseContentTransformer创建transformErrors: true。)

使用SwiftyJSON的另一种方法是,在每个单独的响应转换器中手动包装JSON中的内容,这种方法不是很漂亮但需要较少的设置。

service.configureTransformer("/users/*/repos") {
  JSON($0.content as AnyObject).arrayValue.map(Incident.init)
}