Skip to content

Conversation

@daniCsorbaJB
Copy link

@daniCsorbaJB daniCsorbaJB commented Oct 30, 2025

This is the fifth part of the Kotlin Serialization rewrite task.

Related Youtrack ticket: KT-81979


* Serialize Kotlin objects to JSON strings using the [`encodeToString()`](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/encode-to-string.html) function.
* Deserialize JSON strings back to Kotlin objects with the [`decodeFromString()`](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/decode-from-string.html) function.
* Work directly with the [`JsonElement`](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json-element/) when handling complex JSON structures using the [`encodeToJsonElement()`](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/encode-to-json-element.html) and the [`decodeFromJsonElement()`](https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/decode-from-json-element.html) functions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we can nicely add encodeToStream/decodeFromStream to the list here. IMO it's OK to add a separate page for them + Okio integration

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it definitely fits neatly here 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. Oh, and Okio's encodeToSink/decodeFromSource can also go there

Copy link
Member

@sandwwraith sandwwraith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look through io-sources.md since it is not finished


The following sections cover the various `Json` class configuration features.

### Pretty printing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think that placing this setting first is a great idea; its use cases are quite niche. I think we can still put it into 'Customize Json structure' even though it is not directly related.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm 🤔 if it doesn't fit that one, perhaps we could place it afterward? (so before customize JSON serialization) or perhaps even at the very bottom? (before what's next)🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it might be ok to just place it in there after all. It feels like a choice of inflating its importance or slightly miscategorizing it. 🤔 Both feel undesired — perhaps placing it at the bottom would be my preference of these options. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with placing it last in the 'Customize Json structure' section. IMO it is lost completely at the end of the whole page


In this example, `Inner` throws a `SerializationException` for unknown keys because it isn't annotated with `@JsonIgnoreUnknownKeys`.

### Coerce input values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting is quite useful, can we place it first in the section?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure thing 👍 — my only concern is it might be a bit more complex than the ones before — so perhaps it might be better as the second? What do you think? 🤔 (perh after isLenient)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lenient parsing is also quite rare option. We can do the following order then:

- Ignore unknown keys
- Coerce input values
- Trailing commas
- Comments
- Lenient parsing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice — this order sounds good to me 👌
I changed it in the next commit

### Allow special floating-point values

By default, special floating-point values like [`Double.NaN`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/-na-n.html)
and infinities aren't supported in JSON because the JSON specification prohibits them.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can give here link to https://datatracker.ietf.org/doc/html/rfc8259#section-6, although it is not strictly necessary

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to add it or not?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I think we can — I don't think it would take the attention away, and if someone is interested, they can follow it. — I added it 👍

```

> You can iterate through sequences returned by `.decodeToSequence()` only once
> because they are tied to the underlying stream.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add here "Closing the stream before returned sequence is evaluated completely may result in IOException."

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be "absolute" here?
Not sure if I understand correctly — so please correct me if I'm wrong:
Closing the stream early may result in IOException.

The may is based if the sequence was fully evaluated or not? 🤔

So could we write:
Closing the stream before the sequence is fully evaluated causes an IOException.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "may" is based on whether you try to use it after closing or not. If you take the first element from the sequence, then close the stream, Iterator.next() function will throw IOExc. However, if you do not attempt to access the next element, it will be discarded, even if the sequence is not fully evaluated and there are still unparsed elements. Besides, there's buffering and such, so it is non-trivial to say whether there would be an exception at all if all the data got into the buffer.

So it is "Closing the stream before the returned sequence is evaluated completely may result in IOException" or even more, "If the sequence is not evaluated completely, but the underlying stream is closed, accessing it may result in an exception."

NB: I checked kotlinx-io docs and they throw IllegalStateException if the stream is accessed after closing, so it is not limited only to IOException here.

Copy link
Author

@daniCsorbaJB daniCsorbaJB Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see — thank you! 🤔 it might be a bit heavy for a note to add an encompassing explanation when this happens. So what do you think about this version (slight modification on your second suggestion, shifting the focs to the part about accessing the sequence causing the exception, and just saying exception instead of IOException):

Accessing a sequence may result in an exception if its underlying stream is closed before the sequence is completely evaluated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing a sequence may result in an exception if its underlying stream is closed before the sequence is completely evaluated.

Sounds great, let's take this version 👍🏻

```

> You can iterate through sequences returned by `.decodeSourceToSequence()` only once
> because they are tied to the underlying `Source`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add "Closing the stream before returned sequence is evaluated completely may result in IOException." here as well

> You can iterate through sequences returned by `.decodeSourceToSequence()` only once
> because they are tied to the underlying `Source`.
>
{style="note"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have What's next section?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes — good point! 💯 I think we should reuse the one from Customize the Json instance

What's next

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding * Learn how to [customize Json instances](serialization-json-configuration.md) to address different use cases for serialization and deserialization. is also worth it.

Copy link
Member

@sandwwraith sandwwraith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See unresolved conversations

>
{style="note"}

## Okio
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we've added this part here? It wasn't in the inital doc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, unintentional thank you — removed it 👍

```

> You can iterate through sequences returned by `.decodeToSequence()` only once
> because they are tied to the underlying stream.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "may" is based on whether you try to use it after closing or not. If you take the first element from the sequence, then close the stream, Iterator.next() function will throw IOExc. However, if you do not attempt to access the next element, it will be discarded, even if the sequence is not fully evaluated and there are still unparsed elements. Besides, there's buffering and such, so it is non-trivial to say whether there would be an exception at all if all the data got into the buffer.

So it is "Closing the stream before the returned sequence is evaluated completely may result in IOException" or even more, "If the sequence is not evaluated completely, but the underlying stream is closed, accessing it may result in an exception."

NB: I checked kotlinx-io docs and they throw IllegalStateException if the stream is accessed after closing, so it is not limited only to IOException here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants