我正在构建一个需要使用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)
}
我错过了什么吗?
答案 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)
}