I need to share, my first stack overflow in Kotlin and I’m happy :D

Hi, I have 14 years of my career as professional developer behind me. This was in C # and Microsoft dotnet and dotnet core. Now I’m starting with Kotlin via JetBrains academy. Just now I have my first stack overflow error. That’s good, because I’m feeling like back on horse if you get what I mean.

submitted by /u/brut4r
[link] [comments]

Continue ReadingI need to share, my first stack overflow in Kotlin and I’m happy :D

Kotlin articles & Kotlin Coroutines workshop from Kt. Academy

Hello!
Kt. Academy here 👋

This time we have prepared 4 articles for Kotlin-lovers!

*️⃣ We’d love to hear your thoughts and suggestions for this newsletter. Please share them with us by replying to this email 📩

Here is a brief summary of today’s content 👇

Articles
👉 Job and children awaiting in Kotlin coroutines
👉 Cancellation in Kotlin Coroutines
👉 Effective Kotlin Item 51: Prefer Sequence for big collections with more than one processing step
👉 Effective Kotlin Item 52: Consider associating elements to a map

Kotlin Coroutines open workshop happening soon 🥳

Enjoy! ⏬

What is Job and how it is the most important context responsible for structured concurrency?

Job and children awaiting in Kotlin Coroutines by Marcin Moskala 👇


Kotlin articles & Kotlin Coroutines workshop from Kt. Academy was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingKotlin articles & Kotlin Coroutines workshop from Kt. Academy

How to debug generated API in kotlin – responseBody supports only JSON body error

So my issue is that I am trying to send a text snippet to my app and I used the OpenApi generated library, here is the function where it goes awry:


protected inline fun <reified T: Any?> responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { if(body == null) { return null } println("INSIDE responseBODY $body") val bodyContent = body.string() println("bodyContent $bodyContent") if (bodyContent.isEmpty()) { return null } println("mediaType $mediaType") val jsonBodyContent = JSONObject(bodyContent) println("JSON BodyConent $jsonBodyContent") return when(mediaType) { JsonMediaType -> { println("Serializer ") println(Serializer.moshi.adapter(T::class.java).fromJson(bodyContent)) Serializer.moshi.adapter(T::class.java).fromJson(bodyContent) } else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.") } }

The console logs:


bodyContent {"os":"7c8092ef-74cd-4fda-b24e-804d975788a3","application":{"id":"4f789733-eef7-465b-a5d3-680329fb5f80","name":"JETBRAINS","version":"1.0.0","platform":"MACOS","onboarded":false}} mediaType text/plain JSON BodyConent {"os":"7c8092ef-74cd-4fda-b24e-804d975788a3","application":{"onboarded":false,"name":"JETBRAINS","id":"4f789733-eef7-465b-a5d3-680329fb5f80","version":"1.0.0","platform":"MACOS"}} 2021-09-27 15:09:55,971 [ 108564] ERROR - llij.ide.plugins.PluginManager - responseBody currently only supports JSON body.

I am not sure how to transform the bodyContent ( and if I should?) into json since it does look like a json, but the mediaType is text/plain. Any tips? Thank you.

submitted by /u/SopotSPA
[link] [comments]

Continue ReadingHow to debug generated API in kotlin – responseBody supports only JSON body error

kotlinx.serialization 1.3 Released: Experimental IO Stream-Based JSON Serialization, Fine-Grained Defaults Control, and More

A new version of the Kotlin serialization library – 1.3.0 – is now available following the release of Kotlin 1.5.30. It mainly focuses on broadening the JSON serialization capabilities. Here are the most noticeable changes:

Read this blog post to learn about all these new features, or jump right to the How to try section to start exploring them for yourself.

Start using kotlinx.serialization 1.3

Java IO stream-based JSON serialization

Serialization to Java IO streams and deserialization from them has been requested by our users for quite some time. The corresponding GitHub issue is one of the oldest in our repository and has received a huge number of upvotes.

In

kotlinx.serialization

1.3.0, we’re finally presenting the first experimental version of the serialization API for IO streams. With this API, you can decode objects directly from files, network streams, and other data sources without reading the data to strings beforehand. The opposite operation is also available: you can send encoded objects directly to files and other streams in a single API call.

IO stream serialization is currently available only on the JVM platform and for the JSON format.

The API includes two main methods:

This is how you can read a JSON object from a URL and write it to a file:

@Serializable
data class Project(
    val name: String,
    val language: String,
)

@OptIn(ExperimentalSerializationApi::class)
fun main() {
    URL("https://example.com/project.json").openStream().use {
        val project = Json.decodeFromStream<Project>(it) // read JSON from a URL
        println(project)

        FileOutputStream(File("project.json")).use {  // and save to a file
            Json.encodeToStream(project, it)
        }
    }
}

Note that only UTF-8 streams are currently supported.

This is just the first step, and there is still a lot of work to do. Please give the IO stream serialization API a try in your projects and share your feedback with us on the GitHub issue tracker.

Property-level control over default value encoding

kotlinx.serialization

reduces the size of the JSON that results when serializing objects by omitting the default values of object properties. Default values are defined in the class declaration and automatically assigned if the corresponding property is not initialized in the code:

data class Project(
    val name: String,
    val language: String,
    val version: String? = "1.3.0", //default value
)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin") // version is “1.3.0” by default
}

The JSON strings produced by a default

Json

configuration won’t contain object properties with default values. When decoding such JSON strings, all omitted properties receive their default values as defined in the class declaration.

However, you can force the library to encode the default values by setting the

encodeDefaults

property of a

Json

instance to

true

:

val format = Json { encodeDefaults = true }

@Serializable
data class Project(
    val name: String,
    val language: String,
    val version: String? = "1.3.0",
)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin") // version is “1.3.0” by default
    val json = format.encodeToString(data)
    println(json) // {"name":"kotlinx.serialization","language":"Kotlin","version":"1.3.0"}
    println(format.decodeFromString<Project>(json)) //Project(name=kotlinx.serialization, language=Kotlin, version=1.3.0)
}

This feature was already available, and in 1.3.0 we’re extending it by adding a new way to fine-tune the serialization of default values: you can now control it at the property level using the experimental

@EncodeDefault

annotation. This has a higher priority level than the

encodeDefaults

property and takes one of two possible values:

  • ALWAYS

    (default value) encodes a property value even if it is equal to the default.

  • NEVER

    doesn’t encode the default value regardless of the

    Json

    configuration.

@Serializable
@OptIn(ExperimentalSerializationApi::class)
data class Project(
    val name: String,
    val language: String,
    @EncodeDefault(EncodeDefault.Mode.ALWAYS) val version: String? = "1.3.0",
    // or just
    // @EncodeDefault val version: String? = "1.3.0",
)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin") // version is “1.3.0” by default
    val json = Json.encodeToString(data)
    println(json) // {"name":"kotlinx.serialization","language":"Kotlin","version":"1.3.0"}
    // default version is in JSON although encodeDefaults = false
}

The encoding of the annotated properties is not affected by

encodeDefaults

and works as described for all serialization formats, not only JSON.

Excluding null values from serialization

In 1.3.0, we’re introducing another way to reduce the size of the generated JSON strings – omitting null values.

A new JSON configuration property,

explicitNulls

, defines whether

null

property values should be included in the serialized JSON string. It’s

true

by default, so all nulls are stored as the values of their corresponding properties.

@Serializable
data class Project(
    val name: String,
    val language: String,
    val version: String? = "1.3.0",
    val website: String?
)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin", null, null)
    val json = Json.encodeToString(data)
    println(json) //{"name":"kotlinx.serialization","language":"Kotlin","version":"null","website":"null"}
}

You can make the resulting JSON shorter by excluding the null properties from serialization: just use a

Json

instance with

explicitNulls = false

:

@OptIn(ExperimentalSerializationApi::class)
val format = Json { explicitNulls = false }

@Serializable
data class Project(
    val name: String,
    val language: String,
    val version: String? = "1.3.0",
    val website: String?,
)

fun main() {
    val data = Project("kotlinx.serialization", "Kotlin", null, null)
    val json = format.encodeToString(data)
    println(json) // {"name":"kotlinx.serialization","language":"Kotlin"}

The resulting JSON string contains only non-null properties. 

To deserialize objects from JSON with omitted nulls, you also need  a

Json

instance with

explicitNulls == false

. Such configuration sets all omitted nullable properties to

null

unless they have default values. In this case, the default value is used. This is how the

json

string from this snippet is decoded:

println(format.decodeFromString<Project>(json))
//Project(name=kotlinx.serialization, language=Kotlin, version=1.3.0, website=null)

Trying to use a

Json

configuration with

explicitNulls == true

(the default setting) to decode a JSON string with omitted nulls will result in a

MissingFieldException

.

Custom polymorphic class discriminators

When it comes to class hierarchies, serialization may get a bit difficult because of the additional need to support polymorphism in serialization operations. There are recommended ways to deal with the serialization of hierarchies: make them sealed, annotate each class in the hierarchy as

@Serializable

, and so on. This documentation page explains in detail how to handle such cases.

In hierarchy serialization, a useful attribute comes into play – class discriminator. It serves as a key for a property that stores the exact class of the object that was encoded. By default, the discriminator has the name

“type”

and contains a fully qualified class name of the object being serialized, for example:

@Serializable
sealed class Project {
    abstract val name: String
}

@Serializable
class OwnedProject(override val name: String, val owner: String) : Project()

fun main() {
    val data: Project = OwnedProject("kotlinx.serialization", "kotlin")
    println(Json.encodeToString(data))
// {"type":"org.example.OwnedProject","name":"kotlinx.serialization","owner":"kotlin"}
// “type” property stores the class of the serialized object
} 

In previous versions, you could change the discriminator name using the classDiscriminator property of the

Json

instance. Given the hierarchy above, you could write:

val format = Json { classDiscriminator = "#className" }

fun main() {
    val data: Project = OwnedProject("kotlinx.serialization", "kotlin")
    println(format.encodeToString(data))
// {"#className":"org.example.OwnedProject","name":"kotlinx.serialization","owner":"kotlin"}
// Now the discriminator is “#className”. Its value is the same
}

In 1.3.0, we’re adding a way to set a custom discriminator name for each class hierarchy to enable more flexible serialization. You can do this by marking a class with the new experimental annotation @JsonClassDiscriminator, using the discriminator name as its argument.

For example, you can use a word that somehow identifies the whole hierarchy to which an object belongs:

@OptIn(ExperimentalSerializationApi::class)
@Serializable
@JsonClassDiscriminator("projectType")
sealed class Project {
    abstract val name: String
}
            
@Serializable
class OwnedProject(override val name: String, val owner: String) : Project()

fun main() {
    val data: Project = OwnedProject("kotlinx.serialization", "kotlin")
    println(Json.encodeToString(data))
// {"projectType":"org.example.OwnedProject","name":"kotlinx.serialization","owner":"kotlin"}
// Now the discriminator is “projectType”.
} 

A custom discriminator applies to the annotated class and its subclasses. Only one custom discriminator can be used in each class hierarchy.

How to try

To enjoy the new JSON features in

kotlinx.serialization

1.3.0, apply the latest Kotlin serialization Gradle plugin (note that its version corresponds to Kotlin in general, not the library):

plugins {
  kotlin("jvm") version "1.5.31" // or kotlin("multiplatform") or any other Kotlin plugin
  kotlin("plugin.serialization") version "1.5.31"
}

Then add or update the dependency on the JSON serialization library 1.3.0:

dependencies {
  implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0")
// . . .
}

That’s it, you’re ready to go! Try the new features and let us know what you think of them.

If you run into any trouble

Read more

Continue Readingkotlinx.serialization 1.3 Released: Experimental IO Stream-Based JSON Serialization, Fine-Grained Defaults Control, and More

I wrote an API in Kotlin + Flow to make Android Contacts straightforward to use (no ContentProviders)

I am the author of ContactStore for Android.

Historically, using the Contacts API has been a pain. Developers need to use ContentProviders which can be tedious to work with. The lack of a type-safe API leads to repeated errors, developer frustration, along with a waste of time and resources for the developer and the team.

As a result, ContactStore was born. Contact Store is a modern contacts Android API written in Kotlin. It utilises Coroutine’s Flow to notify the developer for updates happening to the Contacts database.

Source code on Github

Your feedback is greatly appreciated 🙏 Follow me on Twitter for further updates

submitted by /u/alexstyl
[link] [comments]

Continue ReadingI wrote an API in Kotlin + Flow to make Android Contacts straightforward to use (no ContentProviders)

End of content

No more pages to load