IkigaJSON Documentation

repository·master·Indexed 19 days ago

https://github.com/orlandos-nl/swift-json

A high-performance JSON parser for Swift designed for low memory footprint and high scalability, particularly for large payloads and server-side environments. It provides Codable support via IkigaJSONDecoder and IkigaJSONEncoder, native SwiftNIO ByteBuffer support, and raw JSON manipulation through JSONObject and JSONArray. Includes integration guides for Hummingbird 2 and Vapor 4, as well as streaming capabilities via StreamingJSONArrayDecoder and StreamingJSONLinesDecoder.

Tokens
2.5K
Snippets
7
Records
7
Agent score
15%

What's inside IkigaJSON

  1. Integrate IkigaJSON with Vapor 4

    master

    To use IkigaJSON in Vapor 4, extend IkigaJSONEncoder to conform to ContentEncoder and IkigaJSONDecoder to conform to ContentDecoder. You must then register them with ContentConfiguration.global.

    extension IkigaJSONEncoder: ContentEncoder {
        public func encode<E: Encodable>(
            _ encodable: E,
            to body: inout ByteBuffer,
            headers: inout HTTPHeaders
        ) throws {
            headers.contentType = .json
            try self.encodeAndWrite(encodable, into: &body)
        }
    
        public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws where E : Encodable {
            var encoder = self
            encoder.userInfo = userInfo
            headers.contentType = .json
            try encoder.encodeAndWrite(encodable, into: &body)
        }
    
        public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws where E : Encodable {
            var encoder = self
            encoder.userInfo = userInfo
            headers.contentType = .json
            try encoder.encodeAndWrite(encodable, into: &body)
        }
    }
    
    extension IkigaJSONDecoder: ContentDecoder {
        public func decode<D: Decodable>(
            _ decodable: D.Type,
            from body: ByteBuffer,
            headers: HTTPHeaders
        ) throws -> D {
            return try self.decode(D.self, from: body)
        }
        
        public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws -> D where D : Decodable {
            let decoder = IkigaJSONDecoder(settings: settings)
            decoder.settings.userInfo = userInfo
            return try decoder.decode(D.self, from: body)
        }
    
        public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws -> D where D : Decodable {
            let decoder = IkigaJSONDecoder(settings: settings)
            decoder.settings.userInfo = userInfo
            return try decoder.decode(D.self, from: body)
        }
    }
    
    // Registration
    var decoder = IkigaJSONDecoder()
    decoder.settings.dateDecodingStrategy = .iso8601
    ContentConfiguration.global.use(decoder: decoder, for: .json)
    
    var encoder = IkigaJSONEncoder()
    encoder.settings.dateEncodingStrategy = .iso8601
    ContentConfiguration.global.use(encoder: encoder, for: .json)
  2. Integrate IkigaJSON with Hummingbird 2

    master

    To use IkigaJSON in Hummingbird 2, extend IkigaJSONEncoder to conform to ResponseEncoder and IkigaJSONDecoder to conform to RequestDecoder.

    extension IkigaJSONEncoder: ResponseEncoder {
        public func encode(_ value: some Encodable, from request: Request, context: some BaseRequestContext) throws -> Response {
            // Capacity should roughly cover the amount of data you regularly expect to encode
            // However, the buffer will grow if needed
            var buffer = context.allocator.buffer(capacity: 2048)
            try self.encodeAndWrite(value, into: &buffer)
            return Response(
                status: .ok, 
                headers: [
                    .contentType: "application/json; charset=utf-8",
                ], 
                body: .init(byteBuffer: buffer)
            )
        }
    }
    
    extension IkigaJSONDecoder: RequestDecoder {
        public func decode<T>(_ type: T.Type, from request: Request, context: some BaseRequestContext) async throws -> T where T : Decodable {
            let data = try await request.body.collate(maxSize: context.maxUploadSize)
            return try self.decode(T.self, from: data)
        }
    }
  3. Add IkigaJSON dependency

    master

    Choose the version of IkigaJSON based on your SwiftNIO dependency. Use version 1.x for SwiftNIO 1.x and version 2.x for SwiftNIO 2.x.

    // SwiftNIO 1.x
    .package(url: "https://github.com/orlandos-nl/IkigaJSON.git", from: "1.0.0"),
    // Or, for SwiftNIO 2
    .package(url: "https://github.com/orlandos-nl/IkigaJSON.git", from: "2.0.0"),
  4. Use IkigaJSON for Codable decoding

    master

    Use IkigaJSONDecoder to decode JSON data into types conforming to Codable. This provides an easy-to-use API similar to Foundation's JSONDecoder.

    import IkigaJSON
    
    struct User: Codable {
        let id: Int
        let name: String
    }
    
    let data: Data = ...
    var decoder = IkigaJSONDecoder()
    let user = try decoder.decode(User.self, from: data)
  5. Stream JSON arrays and JSON Lines

    master

    For large datasets, use StreamingJSONArrayDecoder or StreamingJSONLinesDecoder to parse chunks of data asynchronously as they arrive.

    // Streaming JSON Array
    var decoder = StreamingJSONArrayDecoder(decoding: User.self)
    for try await chunk in request.body {
        let users = try decoder.parseBuffer(chunk)
    }
    
    // Streaming JSON Lines
    var decoder = StreamingJSONLinesDecoder(decoding: User.self)
    for try await chunk in request.body {
        let users = try decoder.parseBuffer(chunk)
    }
  6. Use IkigaJSON with SwiftNIO ByteBuffers

    master

    IkigaJSON has native support for SwiftNIO ByteBuffer. You can initialize a JSONObject directly from a buffer or use the encoder/decoder to work with ByteBuffer directly.

    // Decode from ByteBuffer
    var user = try JSONObject(buffer: byteBuffer)
    print(user["username"].string)
    
    // Decode a collection from ByteBuffer
    let userList = try decoder.decode([User].self, from: byteBuffer)
    
    // Encode into ByteBuffer
    var buffer: ByteBuffer = ...
    try encoder.encodeAndWrite(user, into: &buffer)
  7. Use Raw JSON APIs (JSONObject and JSONArray)

    master

    IkigaJSON provides JSONObject and JSONArray for direct JSON manipulation. Unlike standard Codable workflows, IkigaJSON edits the JSON inline, avoiding conversion overhead between Swift types and JSON.

    var user = JSONObject()
    user["username"] = "Joannis"
    user["roles"] = ["admin", "moderator", "user"] as JSONArray
    user["programmer"] = true
    
    print(user.string)
    
    print(user["username"].string)
    // OR
    print(user["username"] as? String)