MoshiPack

MessagePack implementation built on top of Moshi in Kotlin

License

License

Categories

Categories

Ant Build Tools Moshi Data JSON
GroupId

GroupId

com.daveanthonythomas.moshipack
ArtifactId

ArtifactId

moshipack
Last Version

Last Version

1.0.1
Release Date

Release Date

Type

Type

jar
Description

Description

MoshiPack
MessagePack implementation built on top of Moshi in Kotlin
Project URL

Project URL

https://github.com/davethomas11/MoshiPack
Source Code Management

Source Code Management

https://github.com/davethomas11/MoshiPack/tree/master/moshipack

Download moshipack

How to add to project

<!-- https://jarcasting.com/artifacts/com.daveanthonythomas.moshipack/moshipack/ -->
<dependency>
    <groupId>com.daveanthonythomas.moshipack</groupId>
    <artifactId>moshipack</artifactId>
    <version>1.0.1</version>
</dependency>
// https://jarcasting.com/artifacts/com.daveanthonythomas.moshipack/moshipack/
implementation 'com.daveanthonythomas.moshipack:moshipack:1.0.1'
// https://jarcasting.com/artifacts/com.daveanthonythomas.moshipack/moshipack/
implementation ("com.daveanthonythomas.moshipack:moshipack:1.0.1")
'com.daveanthonythomas.moshipack:moshipack:jar:1.0.1'
<dependency org="com.daveanthonythomas.moshipack" name="moshipack" rev="1.0.1">
  <artifact name="moshipack" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.daveanthonythomas.moshipack', module='moshipack', version='1.0.1')
)
libraryDependencies += "com.daveanthonythomas.moshipack" % "moshipack" % "1.0.1"
[com.daveanthonythomas.moshipack/moshipack "1.0.1"]

Dependencies

compile (3)

Group / Artifact Type Version
org.jetbrains.kotlin : kotlin-stdlib-jdk8 jar 1.3.11
com.squareup.moshi : moshi jar 1.5.0
com.squareup.moshi : moshi-kotlin jar 1.5.0

test (2)

Group / Artifact Type Version
junit : junit jar 4.12
org.msgpack : msgpack-core jar 0.8.14

Project Modules

There are no modules declared in this project.

MoshiPack

CircleCI

Gradle

implementation com.daveanthonythomas.moshipack:moshipack:1.0.1

Optional Retrofit support:

implementation com.daveanthonythomas.moshipack:moshipack-retrofit:1.0.1

About

This is a Kotilin implementation of MessagePack serialization and deserialization built ontop of Moshi to take advantage of Moshi's type adapters and utilizes okio for reading and writing MessagePack bytes.

The library is intended to be consumed in a Kotlin project, and is not intended for Java use.

Inspired by Kaushik Gopal's tweet

See Moshi for adapter usage and reference.

Convert an object to MessagePack format

data class MessagePackWebsitePlug(var compact: Boolean = true, var schema: Int = 0)

val moshiPack = MoshiPack()
val packed: BufferedSource = moshiPack.pack(MessagePackWebsitePlug())

println(packed.readByteString().hex())

This prints the MessagePack bytes as a hex string 82a7636f6d70616374c3a6736368656d6100

  • 82 - Map with two entries
  • a7 - String of seven bytes
  • 63 6f 6d 70 61 63 74 - UTF8 String "compact"
  • c3 - Boolean value true
  • a6 - String of size bytes
  • 73 63 68 65 6d 61 - UTF8 String "schema"
  • 00 - Integer value 0

Convert binary MessagePack back to an Object

val bytes = ByteString.decodeHex("82a7636f6d70616374c3a6736368656d6100").toByteArray()

val moshiPack = MoshiPack()
val plug: MessagePackWebsitePlug = moshiPack.unpack(bytes)

Static API

If you prefer to not instantiate a MoshiPack instance you can access the API in a static fashion as well. Note this will create a new Moshi instance every time you make an API call. You may want to use the API this way if you aren't providing MoshiPack by some form of dependency injection and you do not have any specific builder parameters for Moshi


Format Support

See MessagePack format spec for further reference.

format name first byte (in binary) first byte (in hex) Supported
positive fixint 0xxxxxxx 0x00 - 0x7f Yes
fixmap 1000xxxx 0x80 - 0x8f Yes
fixarray 1001xxxx 0x90 - 0x9f Yes
fixstr 101xxxxx 0xa0 - 0xbf Yes
nil 11000000 0xc0 Yes
(never used) 11000001 0xc1 Yes
false 11000010 0xc2 Yes
true 11000011 0xc3 Yes
bin 8 11000100 0xc4 No
bin 16 11000101 0xc5 No
bin 32 11000110 0xc6 No
ext 8 11000111 0xc7 No
ext 16 11001000 0xc8 No
ext 32 11001001 0xc9 No
float 32 11001010 0xca Yes
float 64 11001011 0xcb Yes
uint 8 11001100 0xcc Yes
uint 16 11001101 0xcd Yes
uint 32 11001110 0xce Yes
uint 64 11001111 0xcf Yes
int 8 11010000 0xd0 Yes
int 16 11010001 0xd1 Yes
int 32 11010010 0xd2 Yes
int 64 11010011 0xd3 Yes
fixext 1 11010100 0xd4 No
fixext 2 11010101 0xd5 No
fixext 4 11010110 0xd6 No
fixext 8 11010111 0xd7 No
fixext 16 11011000 0xd8 No
str 8 11011001 0xd9 Yes
str 16 11011010 0xda Yes
str 32 11011011 0xdb Yes
array 16 11011100 0xdc Yes
array 32 11011101 0xdd Yes
map 16 11011110 0xde Yes
map 32 11011111 0xdf Yes
negative fixint 111xxxxx 0xe0 - 0xff Yes

API

pack

Serializes an object into MessagePack. Returns: okio.BufferedSource

Instance version:

MoshiPack().pack(anyObject)

Static version:

MoshiPack.pack(anyObject)

packToByeArray

If you prefer to get a ByteArray instead of a BufferedSource you can use this method.

Instance version only

MoshiPack().packToByteArray(anObject)

Static can be done

MoshiPack.pack(anObject).readByteArray()

unpack

Deserializes MessagePack bytes into an Object. Returns: T: Any Works with ByteArray and okio.BufferedSource

Instance version:

// T must be valid type so Moshi knows what to deserialize to
val unpacked: T = MoshiPack().unpack(byteArray)

Static version:

val unpacked: T = MoshiPack.upack(byteArray)

Instance version:

val unpacked: T = MoshiPack().unpack(bufferedSource)

Static version:

val unpacked: T = MoshiPack.upack(bufferedSource)

T can be an Object, a List, a Map, and can include generics. Unlike Moshi you do not need to specify a parameterized type to deserialize to a List with generics. MoshiPack can infer the paramterized type for you.

The following examples are valid for MoshiPack:

A typed List

val listCars: List<Car> = MoshiPack.unpack(carMsgPkBytes)

A List of Any

val listCars: List<Any> = MoshiPack.unpack(carMsgPkBytes)

An Object

val car: Car = MoshiPack.unpack(carBytes)

A Map of Any, Any

val car: Map<Any, Any> = MoshiPack.unpack(carBytes)

msgpackToJson

Convert directly from MessagePack bytes to JSON. Use this method for the most effecient implementation as no objects are instantiated in the process. This uses the FormatInterchange class to match implementations of JsonReader and a JsonWriter. If you wanted to say support XML as a direct conversion to and from, you could implement Moshi's JsonReader and JsonWriter classes and use the FormatInterchange class to convert directly to other formats. Returns String containing a JSON representation of the MessagePack data

Instance versions: (takes ByteArray or BufferedSource)

MoshiPack().msgpackToJson(byteArray)
MoshiPack().msgpackToJson(bufferedSource)

Static versions: (takes ByteArray or BufferedSource)

MoshiPack.msgpackToJson(byteArray)
MoshiPack.msgpackToJson(bufferedSource)

jsonToMsgpack

Convert directly from JSON to MessagePack bytes. Use this method for the most effecient implementation as no objects are instantiated in the process. Returns BufferedSource

Instance versions: (takes String or BufferedSource)

MoshiPack().jsonToMsgpack(jsonString)
MoshiPack().jsonToMsgpack(bufferedSource)

Static versions: (takes String or BufferedSource)

MoshiPack.jsonToMsgpack(jsonString)
MoshiPack.jsonToMsgpack(bufferedSource)

MoshiPack - constructor + Moshi builder

The MoshiPack constructor takes an optional Moshi.Builder.() -> Unit lambda which is applied to the builder that is used to instantiate the Moshi instance it uses.

Example adding custom adapter:

val moshiPack = MoshiPack({
  add(customAdapter)
})

Moshi is also a settable property which can be changed on a MoshiPack instance:

val m = MoshiPack()
m.moshi = Moshi.Builder().build()

The static version of the API also can be passed a lambda to applied to the Moshi.Builder used to instantiate Moshi:

MoshiPack.pack(someBytes) { add(customAdapter) }

Forcing integers to write as certain format

  • new in v1.0.1

This will force all integers to be packed as the type given. By default the smallest message pack type is used for integers.

val moshiPack = MoshiPack().apply {
    writerOptions.writeAllIntsAs = MsgpackIntByte.INT_64
}

Kotiln Support

Since this library is intended for Kotlin use, the moshi-kotlin artifact is included as a depedency. A KotlinJsonAdapterFactory is added by default to the instantiated Moshi that MoshiPack uses. This adapter allows for the use of Moshi's annotaions in Kotlin. To learn more about it see the Moshi documentation.

If you'd like to use Moshi with out a KotlinJsonAdapterFactory supply a Moshi instance for MoshiPack:

MoshiPack(moshi = Moshi.Builder().build)

ProGuard

From Moshi's README.md; If you are using ProGuard you might need to add the following options:

-dontwarn okio.**
-dontwarn javax.annotation.**
-keepclasseswithmembers class * {
    @com.squareup.moshi.* <methods>;
}
-keep @com.squareup.moshi.JsonQualifier interface *
-keepclassmembers class kotlin.Metadata {
    public <methods>;
}

Retrofit

An example of using the retorfit adapter can be found here: https://github.com/davethomas11/MoshiPack_AndroidAppExample

Versions

Version
1.0.1
1.0.0-beta