An implementation of the serial format CBOR with Kotlin multiplatform and jetbrains kotlinx-serialization api.
You can find obor library on maven central.
For Jvm:
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:x.y.z")
implementation("net.orandja.obor:obor:2.1.3")
}
For multiplatform:
kotlin {
...
sourceSets {
getByName("commonMain") {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:x.y.z")
implementation("net.orandja.obor:obor:2.1.3")
}
}
}
}
It uses conventionnal encode/decode kotlinx-serialization functions like JSON. You can take a look on how it works here.
import net.orandja.obor.codec.Cbor
import kotlinx.serialization.Serializable
@Serializable
data class Example(val foo: String, val bar: Int)
fun main() {
val example = Example("Hello World !", 42)
val encode = Cbor.encodeToHexString(example)
assert(encode == "a263666f6f6d48656c6c6f20576f726c64202163626172182a")
val decode = Cbor.decodeFromHexString<Example>(encode)
assert(example == decode)
}
The bytes translate to:
A2 # map(2)
63 # text(3)
666F6F # "foo"
6D # text(13)
48656C6C6F20576F726C642021 # "Hello World !"
63 # text(3)
626172 # "bar"
18 2A # unsigned(42)
The Cbor codec can be configured with :
val codec = Cbor {
ingnoreUnknownKeys = false // Set to true to ignore unknown keys during deserialization
}
-
It always uses the least number of bytes to encode something. An Int with a value of less than 24 will be encoded to a single byte. A float32 that can be encoded with a float16 will be encoded as a float16.
-
Like the
JsonObject
, you can use the CborObject to encode / decode anything. Even structures which are challenging to create with the kotlin language. See Handle any data structure -
By implementing the Reader or Writer interface, you are able to read and write CBOR from anything. Know how many bytes were read/written. See Reading and writing to anything
-
There are special serializers (in CborUnsignedSerializer) to serialize and deserialize full range of signed and unsigned values. See Unsigned values
-
Create any tagged CBOR data with the
@CborTag
annotation. See Creating tagged elements -
ByteArray and types looking like
List<Byte>
can be written with Major type 2 instead of Major type 4 with@CborRawBytes
and special serializers. See Handling MAJOR (type 2) bytes and indefinite bytes -
Indefinite length is handled automatically on deserialization and can be specified on serialization with
@CborIndefinite
or special serializers. -
You can compact the serialization of a class to its ordered properties with
@CborTuple
.
{ a: "foo", b: 0 }
->[ "foo", 0 ]
-
You can shrink down the serialization further if a
@CborTuple
is in a list with@CborTuple.inlineInList
.
[{ a: "foo", b: 0 }, { a: "bar", b: 1 }]
->[ "foo", 0, "bar", 1]
-
CborTuple A class or object annotated with it will be serialized as an ordered list of its elements.
-
CborIndefinite Indicates to the codec to always use indefinite length encoding when encoding the annotated value. For example:
class Foo(val a: List<Int>)
->Foo(listOf(0,1))
will be serialized toA16161820001
@CborIndefinite class Foo(val a: List<Int>)
->Foo(listOf(0,1))
will be serialized toBF6161820001FF
-
CborRawBytes When a type looks like a
List<Byte>
(Array<Byte>
,ByteArray
) and is annotated with@CborRawBytes
It will use the major type 2 (byte string) instead of major type 4 (array).class Foo(val a: List<Byte>)
->Foo(listOf(0, 1))
will be serialized toA16161820001
class Foo(@CborRawBytes val a: List<Byte>)
->Foo(listOf(0, 1))
will be serialized toA16161420001
-
CborSkip Annotates a field to skip it during serialization and deserialization
-
CborTag Adds a tag to the specified field or class.
The use of @CborIndefinite
only affects serialization and not deserialization. Unless you use the specific special
serializers as described in Handling MAJOR (type 2) bytes and indefinite bytes
or Handling MAJOR (type 3) indefinite string.
An indefinite marker will be deserialized like a non-indefinite one. For example 0x9f010203ff
and 0x83010203
can
both be
deserialized to listOf(1, 2, 3)
assertEquals(
Cbor.decodeFromHexString<List<Int>>("83010203"),
Cbor.decodeFromHexString<List<Int>>("9f010203ff")
)