You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Alamofire与Codable解析JSON Lines格式数据?

使用Alamofire + Codable解析JSON Lines并转成数组

当然可以实现!我来一步步教你搞定这个需求,顺便给不熟悉JSON Lines的朋友补个基础。

先搞懂什么是JSON Lines

JSON Lines是一种轻量的文本格式,核心规则很简单:每行单独是一个合法的JSON对象,行与行用换行符分隔,没有外层的数组包裹。举个例子:

{"id":1,"name":"Alice"}
{"id":2,"name":"Bob"}
{"id":3,"name":"Charlie"}

这种格式常用于批量数据导出/传输,但Alamofire默认的JSON序列化器不认它——因为标准JSON要求整个响应是单个合法JSON值(要么是数组,要么是单个对象),而JSON Lines是多行独立的JSON,直接用传统方式解析肯定会失败。

解决方案:自定义JSON Lines响应序列化器

我们需要给Alamofire写一个自定义的解析逻辑,把每行的JSON对象单独解析,最后拼成数组。

第一步:实现JSON Lines解码逻辑

先写一个解码器,负责把原始数据拆分成每行,再逐个解析成目标模型:

import Alamofire

struct JSONLinesDecoder {
    static func decode<T: Decodable>(_ type: [T].Type, from data: Data) throws -> [T] {
        // 把二进制数据转成字符串,按换行分割成非空的行
        guard let rawString = String(data: data, encoding: .utf8) else {
            throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
        }
        let jsonLines = rawString.components(separatedBy: .newlines).filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty }
        
        // 遍历每行,用系统的JSONDecoder解析成单个模型,最后组合成数组
        let decoder = JSONDecoder()
        return try jsonLines.map { line in
            guard let lineData = line.data(using: .utf8) else {
                throw AFError.responseSerializationFailed(reason: .invalidUTF8Data)
            }
            return try decoder.decode(T.self, from: lineData)
        }
    }
}

第二步:给Alamofire扩展自定义响应方法

为了调用方便,我们给Request加个扩展,让它支持直接返回解析好的数组:

extension Request {
    func responseJSONLines<T: Decodable>(queue: DispatchQueue = .main, completionHandler: @escaping (Result<[T], AFError>) -> Void) -> Self {
        return response(queue: queue, responseSerializer: DataResponseSerializer { _, response, data, error in
            // 先处理请求层面的错误
            guard let responseData = data, error == nil else {
                return .failure(error ?? AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
            }
            
            // 调用上面的解码器解析数据
            do {
                let parsedArray = try JSONLinesDecoder.decode([T].self, from: responseData)
                return .success(parsedArray)
            } catch {
                return .failure(AFError.responseSerializationFailed(reason: .decodingFailed(error: error)))
            }
        }, completionHandler: completionHandler)
    }
}

第三步:实际使用示例

假设你有一个用户模型:

struct User: Decodable {
    let id: Int
    let name: String
}

现在发起请求就可以直接拿到数组了:

AF.request("https://your-api-url.com/users.jsonl")
    .responseJSONLines { (result: Result<[User], AFError>) in
        switch result {
        case .success(let userArray):
            print("成功解析到\(userArray.count)个用户:\(userArray)")
            // 这里直接用数组就行
        case .failure(let error):
            print("解析失败:\(error.localizedDescription)")
        }
    }

为什么传统方法不行?

再啰嗦一句:Alamofire默认的responseDecodable方法会把整个响应数据当成一个完整的JSON来解析,但JSON Lines是多行独立的JSON,整个内容并不是一个合法的JSON值(没有外层数组/对象包裹),所以直接用传统方式必然会抛出解码错误。我们的自定义逻辑就是把整个响应拆成多行,每行单独解析,最后拼成数组,完美适配JSON Lines的格式。

内容的提问来源于stack exchange,提问作者Nevin Jethmalani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:57:38