An open API service indexing awesome lists of open source software.

https://github.com/lynixliu/swiftavrocore

An implementation of Apache Avro in Swift 5
https://github.com/lynixliu/swiftavrocore

avro codable swift5

Last synced: 3 months ago
JSON representation

An implementation of Apache Avro in Swift 5

Awesome Lists containing this project

README

          

[![Swift](https://github.com/STCData/SwiftAvroCore/actions/workflows/swift.yml/badge.svg)](https://github.com/STCData/SwiftAvroCore/actions/workflows/swift.yml)

# SwiftAvroCore

The SwiftAvroCore framework implements the core coding functionalities that are required in Apache Avro™. The schema format support Avro 1.8.2 and later Specification. It provides user-friendly Codable interface introduced from Swift 5 to encode and decode Avro schema, binray data as well as the JSON format data.

It is designed to achieve the following goals:

* to provide a small set of core functionalities defined in Avro specification;
* to make software development easier by introducing Codable interface;
* to provide platform independence and a self-contained framework to enhance portability.

This project, `SwiftAvroCore`, provides an implementation of the coding API for all Swift platforms which provide Foundation framework. The file IO and RPC functions defined in Avro specification will be provided in a seperate project `SwiftAvroRpc` which depends on the swift-nio framework.

## Getting Started

SwiftAvroCore uses SwiftPM as its build tool. If you want to depend on SwiftAvroCore in your own project, it's as simple as adding a dependencies clause to your Package.swift:

dependencies: [
.package(url: "https://github.com/lynixliu/SwiftAvroCore")
]
and then adding the SwiftAvroCore module to your target dependencies.

To work on SwiftAvroCore itself, or to investigate some of the demonstration applications, you can clone the repository directly and use SwiftPM to help build it. For example, you can run the following commands to compile and run the example:

swift build
swift test

To generate an Xcode project to work on SwiftAvroCore in Xcode:

swift package generate-xcodeproj

This generates an Xcode project using SwiftPM. You can open the project with:

open SwiftAvroCore.xcodeproj

## Using SwiftAvroCore

This guide assumes you have already installed a version of the latest [Swift binary distribution](https://swift.org/download/#latest-development-snapshots).
Suppose you have a schema in JSON format as shown below:
```
// The JSON schema
let jsonSchema = """
{"type":"record",
"fields":[
{"name": "requestId", "type": "int"},
{"name": "requestName", "type": "string"},
{"name": "parameter", "type": {"type":"array", "items": "int"}}
]}
"""
```

### Encoding and decoding

Here is a simple `main.swift` file which uses SwiftAvroCore.
```
// main.swift
import Foundation
import SwiftAvroCore

// Define your model in Swift
struct Model: Encodable {
let requestId: Int32 = 1
let requestName: String = "hello"
let parameter: [Int32] = []
}

// Make an Avro instance
let avro = Avro()
let myModel = Model(requestId: 42, requestName: "hello", parameter: [1,2])

// Decode schema from json
_ = avro.decodeSchema(schema: jsonSchema)!

// encode to avro binray
let binaryValue = try!avro.encode(myModel)

// decode from avro binary
let decodedValue: Model = try! avro.decode(from: binaryValue)

// check result
print("\(decodedValue.requestId), \(decodedValue.requestName), \(decodedValue.parameter)")

// decode from avro binary to Any Type in case of the receiving type unknown
let decodedAnyValue = try! avro.decode(from: binaryValue)

// check type
type(of: decodedAnyValue!)
```

Generate JSON schema for out side
```
let encodedSchema = try avro.encodeSchema(schema: schema)

print(String(bytes: encodedSchema!, encoding: .utf8)!)
```

### The Type mapping when Decode to Any type

Primitive type:

* null: nil
* boolean: Bool
* int: Int
* long: Int64
* float: Float
* double: Double
* bytes: [UInt8]
* string: String
* fixed: [UInt8] or [uint32] for Date

complex type:

* array: [primitive type] or [Any]
* record: [String: primitive type] or [String:Any], the reflect in Swift is readonly, so we cannot generate struct in run time
* enum: String, value in symbols
* map: [String: ] or [String: Any]
* union: optional type Any? or ?

### File IO

```
// define codec
let codec = NullCodec(codecName: AvroReservedConstants.NullCodec)

// define 2 File Object Containers
var oc1 = try? ObjectContainer(schema: """
{
"type": "record",
"name": "test",
"fields" : [
{"name": "a", "type": "long"},
{"name": "b", "type": "string"}]
}
""", codec: codec)
var oc2 = oc1

// test model
struct model: Codable {
var a: UInt64 = 1
var b: String = "hello"
}

// add model to container
try oc1?.addObject(model())

// encode object
let out = try! oc1?.encodeObject()

// write to file
try out?.write(to: URL(fileURLWithPath: "/location/to/save/file"))

// decode object heade
try oc2?.decodeHeader(from: out!)

// decode objec
let start = oc2?.findMarker(from: out!)
try oc2?.decodeBlock(from: out!.subdata(in: start!..